/* Brieflings — Components
 * Each component grouped with its variants and states.
 * Visual treatment: see docs/company/design-language.md
 * Tokens: see docs/company/design-tokens.md and css/tokens.css
 */

/* ==========================================================================
   Layout & shell
   ========================================================================== */

/* Operator impersonation banner — a loud amber strip above the header
 * shown only while an operator is acting as another user (see base.html).
 * Deliberately theme-independent and high-contrast: a privileged-access
 * warning must read the same in light and dark. Sits in normal flow at
 * the top of the page with a high z-index so it's never obscured by the
 * sticky header below it. */
.impersonation-bar {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-5);
  position: relative;
  z-index: 30;
  background: #b45309;
  color: #fff;
  font-size: 0.9rem;
  text-align: center;
}

.impersonation-bar button {
  padding: 0.3rem 0.85rem;
  background: #fff;
  color: #7c2d12;
  border: 0;
  border-radius: 4px;
  font-weight: 600;
  font-size: 0.85rem;
  cursor: pointer;
}

.impersonation-bar button:hover {
  background: #fef3c7;
}

.app-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  padding: var(--space-4) var(--space-5);
  position: sticky;
  inset-block-start: 0;
  z-index: 10;
  background: color-mix(in oklab, var(--bg-page) 80%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-block-end: 1px solid var(--border-subtle);
}

.app-header__nav {
  display: none;
  gap: var(--space-6);
  align-items: center;
}

@media (min-width: 768px) {
  .app-header__nav {
    display: flex;
  }
}

/* Right-side actions zone — sits opposite the brand. Holds the
 * theme toggle plus either Log in + Sign up (unauthed) or the avatar
 * dropdown (authed). Always visible, including on mobile. */
.app-header__actions {
  display: flex;
  gap: var(--space-3);
  align-items: center;
}

@media (min-width: 768px) {
  .app-header__actions {
    gap: var(--space-4);
  }
}

.app-header__nav-link {
  font-family: var(--font-body-sans);
  font-size: var(--text-base);
  color: var(--text-muted);
  font-weight: 400;
  transition: color var(--duration-quick) var(--easing-default);
}

.app-header__nav-link:hover {
  color: var(--text-body);
}

.app-header__nav-link.is-active {
  color: var(--text-body);
  font-weight: 600;
}

/* Brand wordmark
 * Editorial-publication mark: all caps, heavy weight, letterspaced.
 * Controlled imperfection comes from Fraunces' WONK variable axis
 * rather than a CSS hack — the typeface itself carries the character.
 */
.brand {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-body);
  display: inline-block;
  font-variation-settings: 'opsz' 32, 'WONK' 1;
}

.brand em {
  font-style: italic;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-muted);
  font-variation-settings: 'opsz' 14, 'WONK' 0;
  margin-inline-start: var(--space-1);
}

/* Avatar */
.avatar {
  inline-size: 36px;
  block-size: 36px;
  border-radius: 50%;
  background: var(--accent-weekly-bg);
  color: var(--text-body);
  display: grid;
  place-items: center;
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  font-weight: 600;
  border: 1px solid var(--border-subtle);
  flex-shrink: 0;
}

/* Back link */
.back-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
  transition: color var(--duration-quick) var(--easing-default);
}

.back-link:hover {
  color: var(--text-body);
}

/* ==========================================================================
   Containers
   ========================================================================== */

.container-content {
  max-inline-size: var(--container-content);
  margin-inline: auto;
  padding-inline: var(--space-5);
}

.container-reading {
  max-inline-size: var(--container-reading);
  margin-inline: auto;
  padding-inline: var(--space-5);
  /* Breathing room so trailing content (e.g. the topic form's action
     row) doesn't hug the site footer's top border. */
  padding-block-end: var(--space-7);
}

/* Mobile: trim the page gutter to match the tightened settings-card
   padding (var(--space-4)), so the outer page edge and the card's inner
   edge read as one consistent margin instead of a doubled 24px+16px
   squeeze. */
@media (max-width: 767px) {
  .container-content,
  .container-reading {
    padding-inline: var(--space-4);
  }
}

/* ==========================================================================
   Typography blocks
   ========================================================================== */

/* Display headline — used in covers, page titles */
.display {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--text-body);
  font-variation-settings: 'opsz' 72;
}

.display--page {
  font-size: var(--text-3xl);
}

@media (min-width: 768px) {
  .display--page {
    font-size: var(--text-4xl);
  }
}

.display--hero {
  font-size: var(--text-4xl);
  font-variation-settings: 'opsz' 144;
}

@media (min-width: 768px) {
  .display--hero {
    font-size: var(--text-5xl);
  }
}

@media (min-width: 1024px) {
  .display--hero {
    font-size: var(--text-6xl);
  }
}

/* Drop indent — used for cover headlines */
.drop-indent {
  margin-inline-start: var(--space-5);
}

@media (min-width: 768px) {
  .drop-indent {
    margin-inline-start: var(--space-7);
  }
}

/* Standfirst */
.standfirst {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--text-body);
  font-weight: 400;
  max-inline-size: 50ch;
}

/* Pull quote */
.pull-quote {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-xl);
  line-height: var(--leading-snug);
  color: var(--text-body);
  font-weight: 400;
  margin-block: var(--space-5);
  max-inline-size: 36ch;
}

@media (min-width: 1024px) {
  .pull-quote {
    margin-inline-start: -32px;
  }
}

/* Eyebrow */
.eyebrow {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  color: var(--text-muted);
  text-transform: uppercase;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
  line-height: var(--leading-normal);
}

.eyebrow__sep {
  color: var(--text-faint);
}

.eyebrow__sep::before {
  content: '·';
  margin-inline-end: var(--space-2);
}

/* Sign-off block */
.sign-off {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-block: var(--space-8) var(--space-7);
}

.sign-off::before,
.sign-off::after {
  content: '';
  flex: 1;
  border-block-start: 1px solid var(--border-subtle);
}

.sign-off__text {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-md);
  color: var(--text-muted);
  text-align: center;
  white-space: nowrap;
}

/* Ornament variant — same hairline rule structure but with a small
 * decorative glyph in the middle instead of italic text. Used to open
 * an editorial empty-state block. */
.sign-off--ornament {
  margin-block: var(--space-6) var(--space-7);
}

.sign-off__glyph {
  font-family: var(--font-display);
  font-size: var(--text-md);
  line-height: 1;
  color: var(--text-faint);
  white-space: nowrap;
}

/* Soft variant — tighter surrounding margins for use inside other
 * containers (e.g. the editorial empty state) where the standard
 * sign-off margins would be excessive. */
.sign-off--soft {
  margin-block: var(--space-7) var(--space-3);
}

/* Section opener */
.section-opener {
  margin-block: var(--space-7) var(--space-5);
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.section-opener__line {
  flex: 0 0 40%;
  border-block-start: 1px solid var(--border-subtle);
}

.section-opener__label {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  color: var(--text-muted);
  text-transform: uppercase;
  /* Controlled imperfection — label sits slightly below the hairline */
  transform: translateY(2px);
}

/* ==========================================================================
   Brief card
   ========================================================================== */

.brief-card {
  display: block;
  position: relative;
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: var(--space-5) var(--space-5) var(--space-5) var(--space-6);
  box-shadow: var(--shadow-card);
  transition:
    transform var(--duration-quick) var(--easing-default),
    box-shadow var(--duration-quick) var(--easing-default);
}

.brief-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-card-hover);
}

/* Cadence accent strip */
.brief-card::before {
  content: '';
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  inline-size: 3px;
  background: var(--accent-strip, var(--accent-weekly));
  border-start-start-radius: var(--radius-md);
  border-end-start-radius: var(--radius-md);
}

@media (min-width: 1024px) {
  .brief-card::before {
    inset-inline-start: -16px;
    border-radius: var(--radius-pill);
  }
}

.brief-card[data-cadence='daily'] {
  --accent-strip: var(--accent-daily);
}

.brief-card[data-cadence='weekly'] {
  --accent-strip: var(--accent-weekly);
}

.brief-card[data-cadence='monthly'] {
  --accent-strip: var(--accent-monthly);
}

/* Read state has no per-card visual penalty — the "since you last
 * visited" divider in the feed is the only chronological signal.
 * Caught-up should feel like a finished stack of issues, not a
 * depleted one. */
.brief-card.is-read {
  /* intentionally empty — kept as a hook for future state styling */
}

.brief-card__title {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
  margin-block: var(--space-3);
  color: var(--text-body);
  font-variation-settings: 'opsz' 36;
}

.brief-card__preview {
  font-family: var(--font-body-sans);
  font-size: var(--text-base);
  color: var(--text-muted);
  line-height: var(--leading-normal);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.brief-card__meta {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  color: var(--text-faint);
  margin-block-start: var(--space-4);
  text-transform: uppercase;
}

/* ==========================================================================
   Greeting (front-page header)
   ========================================================================== */

.greeting {
  margin-block: var(--space-7) var(--space-6);
  padding-inline-start: var(--space-3);
}

/* Editorial drop-indent on tablet+ — same value as `.drop-indent` so the
 * greeting reads as a deliberate signature rather than misalignment with
 * the cards underneath. */
@media (min-width: 768px) {
  .greeting {
    padding-inline-start: var(--space-7);
  }
}

.greeting__title {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 600;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--text-body);
  margin-block-end: var(--space-2);
  font-variation-settings: 'opsz' 96;
}

@media (min-width: 768px) {
  .greeting__title {
    font-size: var(--text-4xl);
  }
}

.greeting__subtitle {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  color: var(--text-muted);
  font-style: italic;
}

/* ==========================================================================
   Brief feed (list of brief cards)
   ========================================================================== */

.brief-feed {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  margin-block: var(--space-6) var(--space-9);
}

.brief-feed__divider {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-block: var(--space-3);
}

.brief-feed__divider::before,
.brief-feed__divider::after {
  content: '';
  flex: 1;
  border-block-start: 1px dashed var(--border-subtle);
}

.brief-feed__divider-label {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  color: var(--text-faint);
  text-transform: uppercase;
}

/* ==========================================================================
   Cover (brief detail hero)
   ========================================================================== */

.cover {
  position: relative;
  padding: var(--space-7) var(--space-5);
  margin-inline: calc(var(--space-5) * -1);
  background:
    radial-gradient(ellipse at 80% 0%, var(--cover-tint, var(--accent-weekly-bg)) 0%, transparent 60%),
    linear-gradient(135deg, var(--cover-tint-2, var(--accent-weekly-bg)) 0%, var(--bg-page) 70%);
  overflow: hidden;
  isolation: isolate;
}

@media (min-width: 768px) {
  .cover {
    padding: var(--space-9) var(--space-7) var(--space-8);
    border-radius: var(--radius-xl);
    margin-inline: calc(var(--space-7) * -1);
  }
}

@media (min-width: 1024px) {
  .cover {
    /* Asymmetric breakout — bleeds right past column */
    margin-inline-end: -120px;
    padding-inline-end: var(--space-9);
  }
}

.cover[data-cadence='daily'] {
  --cover-tint: var(--accent-daily-bg);
  --cover-tint-2: color-mix(in oklab, var(--accent-daily) 35%, transparent);
}

.cover[data-cadence='weekly'] {
  --cover-tint: var(--accent-weekly-bg);
  --cover-tint-2: color-mix(in oklab, var(--accent-weekly) 35%, transparent);
}

.cover[data-cadence='monthly'] {
  --cover-tint: var(--accent-monthly-bg);
  --cover-tint-2: color-mix(in oklab, var(--accent-monthly) 35%, transparent);
}

/* Abstract shape behind type */
.cover__shape {
  position: absolute;
  inset-block-start: -30%;
  inset-inline-end: -10%;
  inline-size: 60%;
  aspect-ratio: 1 / 1;
  background: radial-gradient(circle, var(--cover-tint-2) 0%, transparent 70%);
  border-radius: 60% 40% 70% 30% / 50% 60% 40% 50%;
  filter: blur(40px);
  opacity: 0.7;
  z-index: -1;
  pointer-events: none;
}

.cover__eyebrow {
  margin-block-end: var(--space-5);
}

.cover__headline {
  margin-block-end: var(--space-5);
}

.cover__standfirst {
  margin-block: var(--space-5);
}

.cover__actions {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-block-start: var(--space-6);
  flex-wrap: wrap;
}

/* ==========================================================================
   Reaction button & reactions row
   ========================================================================== */

.reactions {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}

.reaction-button {
  inline-size: 44px;
  block-size: 44px;
  border-radius: 50%;
  background: color-mix(in oklab, var(--bg-card) 70%, transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--border-subtle);
  display: grid;
  place-items: center;
  color: var(--text-muted);
  transition:
    background var(--duration-quick) var(--easing-default),
    color var(--duration-quick) var(--easing-default),
    transform var(--duration-quick) var(--easing-default),
    box-shadow var(--duration-quick) var(--easing-default);
}

.reaction-button:hover {
  background: var(--bg-card);
  color: var(--text-body);
  transform: translateY(-1px);
  box-shadow: var(--shadow-card);
}

.reaction-button.is-active {
  background: var(--accent-bg, var(--accent-weekly-bg));
  color: var(--accent-color, var(--accent-weekly));
  border-color: transparent;
}

.reaction-button[data-cadence='daily'].is-active {
  --accent-bg: var(--accent-daily-bg);
  --accent-color: var(--accent-daily);
}

.reaction-button[data-cadence='weekly'].is-active {
  --accent-bg: var(--accent-weekly-bg);
  --accent-color: var(--accent-weekly);
}

.reaction-button[data-cadence='monthly'].is-active {
  --accent-bg: var(--accent-monthly-bg);
  --accent-color: var(--accent-monthly);
}

.reaction-button svg {
  inline-size: 20px;
  block-size: 20px;
  stroke-width: 1.5;
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ==========================================================================
   Bookmark button

   A standalone toggle on a finding — "save this to finish reading later".
   Shares the round icon-button shape of .reaction-button, but is its own
   component: it carries a single binary state (.is-bookmarked) and is used
   without a cadence accent, since bookmarks are a cross-topic surface.
   ========================================================================== */

.bookmark-button {
  inline-size: 44px;
  block-size: 44px;
  border-radius: 50%;
  background: color-mix(in oklab, var(--bg-card) 70%, transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--border-subtle);
  display: grid;
  place-items: center;
  color: var(--text-muted);
  transition:
    background var(--duration-quick) var(--easing-default),
    color var(--duration-quick) var(--easing-default),
    transform var(--duration-quick) var(--easing-default),
    box-shadow var(--duration-quick) var(--easing-default);
}

.bookmark-button:hover {
  background: var(--bg-card);
  color: var(--text-body);
  transform: translateY(-1px);
  box-shadow: var(--shadow-card);
}

.bookmark-button.is-bookmarked {
  background: var(--accent-weekly-bg);
  color: var(--accent-weekly);
  border-color: transparent;
}

.bookmark-button svg {
  inline-size: 20px;
  block-size: 20px;
  stroke-width: 1.5;
  stroke: currentColor;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.bookmark-button.is-bookmarked svg {
  fill: currentColor;
}

/* ==========================================================================
   Source pill & sources row
   ========================================================================== */

.sources {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.source-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  background: color-mix(in oklab, var(--bg-card) 70%, transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-body);
  transition:
    background var(--duration-quick) var(--easing-default),
    box-shadow var(--duration-quick) var(--easing-default);
  max-inline-size: 240px;
}

.source-pill:hover {
  background: var(--bg-card);
  box-shadow: var(--shadow-card);
}

.source-pill__title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ==========================================================================
   Cadence pill / review tag
   ========================================================================== */

.cadence-pill {
  display: inline-flex;
  align-items: center;
  padding: 2px var(--space-3);
  border-radius: var(--radius-pill);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  background: var(--cadence-pill-bg, var(--accent-weekly-bg));
  color: var(--text-body);
}

.cadence-pill[data-cadence='daily'] {
  --cadence-pill-bg: var(--accent-daily-bg);
}

.cadence-pill[data-cadence='weekly'] {
  --cadence-pill-bg: var(--accent-weekly-bg);
}

.cadence-pill[data-cadence='monthly'] {
  --cadence-pill-bg: var(--accent-monthly-bg);
}

.review-tag {
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-body);
  font-weight: 600;
  padding: 1px var(--space-2);
  border: 1px solid currentColor;
  border-radius: var(--radius-pill);
  opacity: 0.7;
}

/* ==========================================================================
   Finding card (in-brief, full body variant)
   ========================================================================== */

.finding-card {
  position: relative;
  padding-inline-start: var(--space-5);
  margin-block: var(--space-6);
  border-inline-start: 3px solid var(--accent-strip, var(--accent-weekly));
}

.finding-card[data-cadence='daily'] {
  --accent-strip: var(--accent-daily);
}

.finding-card[data-cadence='weekly'] {
  --accent-strip: var(--accent-weekly);
}

.finding-card[data-cadence='monthly'] {
  --accent-strip: var(--accent-monthly);
}

.finding-card__title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
  margin-block-end: var(--space-3);
  color: var(--text-body);
  font-variation-settings: 'opsz' 30;
}

.finding-card__body {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--text-body);
  margin-block-end: var(--space-4);
}

.finding-card__sources {
  margin-block: var(--space-4);
}

.finding-card__actions {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  margin-block-start: var(--space-4);
  flex-wrap: wrap;
}

/* ==========================================================================
   Compact item
   ========================================================================== */

.compact-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-block: var(--space-5);
}

.compact-item {
  display: flex;
  gap: var(--space-3);
  align-items: baseline;
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
}

.compact-item::before {
  content: '·';
  color: var(--text-faint);
  flex-shrink: 0;
  font-size: var(--text-xl);
  line-height: 1;
}

.compact-item__title {
  color: var(--text-body);
  font-weight: 500;
}

.compact-item__source {
  color: var(--text-muted);
  font-style: italic;
  font-size: var(--text-base);
  margin-inline-start: var(--space-2);
}

/* ==========================================================================
   Brief navigation (prev / next)
   ========================================================================== */

.brief-nav {
  display: flex;
  justify-content: space-between;
  margin-block: var(--space-7) var(--space-9);
}

.brief-nav__link {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  transition: color var(--duration-quick) var(--easing-default);
}

.brief-nav__link:hover {
  color: var(--text-body);
}

/* ==========================================================================
   Stylebook chrome (only used in stylebook index/reference pages)
   ========================================================================== */

.stylebook-shell {
  min-block-size: 100vh;
  display: flex;
  flex-direction: column;
}

.stylebook-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--space-4) var(--space-5);
  border-block-end: 1px solid var(--border-subtle);
  background: color-mix(in oklab, var(--bg-page) 80%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  position: sticky;
  inset-block-start: 0;
  z-index: 10;
}

.stylebook-header__nav {
  display: flex;
  gap: var(--space-4);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
  align-items: center;
}

.stylebook-header__nav a {
  transition: color var(--duration-quick) var(--easing-default);
}

.stylebook-header__nav a:hover {
  color: var(--text-body);
}

.theme-toggle {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  transition:
    color var(--duration-quick) var(--easing-default),
    border-color var(--duration-quick) var(--easing-default);
}

.theme-toggle:hover {
  color: var(--text-body);
  border-color: var(--text-muted);
}

/* Stylebook index */
.stylebook-index {
  max-inline-size: var(--container-content);
  margin-inline: auto;
  padding: var(--space-8) var(--space-5) var(--space-9);
}

.stylebook-index h1 {
  font-family: var(--font-display);
  font-size: var(--text-5xl);
  font-weight: 600;
  margin-block-end: var(--space-3);
  letter-spacing: var(--tracking-tight);
  font-variation-settings: 'opsz' 144;
}

.stylebook-index__lede {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  font-style: italic;
  color: var(--text-muted);
  margin-block-end: var(--space-7);
  max-inline-size: 50ch;
  line-height: var(--leading-relaxed);
}

.stylebook-index__group {
  margin-block: var(--space-7);
}

.stylebook-index__group-title {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
  margin-block-end: var(--space-2);
}

.stylebook-index__list {
  display: flex;
  flex-direction: column;
}

.stylebook-index__list a {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: var(--space-4) 0;
  border-block-end: 1px solid var(--border-subtle);
  font-family: var(--font-display);
  font-size: var(--text-xl);
  color: var(--text-body);
  font-variation-settings: 'opsz' 36;
  transition: padding-inline-start var(--duration-standard) var(--easing-default);
}

.stylebook-index__list a:hover {
  padding-inline-start: var(--space-3);
}

.stylebook-index__list a span {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
  font-weight: 400;
  font-style: italic;
}

/* Reference pages — token / typography */
.reference {
  max-inline-size: var(--container-content);
  margin-inline: auto;
  padding: var(--space-8) var(--space-5) var(--space-9);
}

.reference h1 {
  font-family: var(--font-display);
  font-size: var(--text-4xl);
  font-weight: 600;
  margin-block-end: var(--space-2);
  letter-spacing: var(--tracking-tight);
  font-variation-settings: 'opsz' 96;
}

.reference > p {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  color: var(--text-muted);
  font-style: italic;
  margin-block-end: var(--space-7);
}

.reference__section {
  margin-block: var(--space-7);
}

.reference__section-title {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
  margin-block-end: var(--space-4);
}

/* Swatch grid (color tokens) */
.swatch-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: var(--space-4);
  margin-block: var(--space-4);
}

.swatch {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  overflow: hidden;
  font-family: var(--font-body-sans);
  background: var(--bg-card);
}

.swatch__sample {
  block-size: 80px;
  background: var(--swatch-color);
}

.swatch__meta {
  padding: var(--space-3);
}

.swatch__name {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-body);
}

.swatch__value {
  font-size: var(--text-xs);
  color: var(--text-muted);
  margin-block-start: var(--space-1);
  font-feature-settings: 'tnum';
}

/* Spacing scale strip */
.scale-strip {
  display: flex;
  align-items: flex-end;
  gap: var(--space-3);
  margin-block: var(--space-4);
}

.scale-strip__step {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  color: var(--text-muted);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
}

.scale-strip__bar {
  inline-size: var(--bar-size);
  block-size: var(--bar-size);
  background: var(--accent-weekly-bg);
  border-radius: var(--radius-sm);
}

/* Type role samples */
.type-sample {
  padding-block: var(--space-5);
  border-block-end: 1px solid var(--border-subtle);
}

.type-sample__label {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
  margin-block-end: var(--space-2);
}

.type-sample__demo {
  color: var(--text-body);
}

.type-sample__demo--display-hero {
  font-family: var(--font-display);
  font-size: var(--text-5xl);
  font-weight: 600;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  font-variation-settings: 'opsz' 144;
}

.type-sample__demo--display-page {
  font-family: var(--font-display);
  font-size: var(--text-4xl);
  font-weight: 600;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  font-variation-settings: 'opsz' 96;
}

.type-sample__demo--display-card {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  line-height: var(--leading-snug);
  font-variation-settings: 'opsz' 36;
}

.type-sample__demo--standfirst {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
}

.type-sample__demo--pull-quote {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-xl);
  line-height: var(--leading-snug);
}

.type-sample__demo--body {
  font-family: var(--font-body-sans);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
}

.type-sample__demo--eyebrow {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* ==========================================================================
   App shell extras (used in apps/web — header dropdown, mobile tab bar)
   ========================================================================== */

/* Account menu (avatar dropdown) and public menu (hamburger) — both
 * use the same <details>/<summary> shell so they share the marker-hiding
 * rules and the sheet positioning. The summary's display comes from
 * the class on it (e.g. .avatar's `display: grid` for the avatar,
 * .theme-icon-button for the hamburger). */
.account-menu,
.public-menu {
  position: relative;
}

.account-menu summary,
.public-menu summary {
  list-style: none;
  cursor: pointer;
}

.account-menu summary::-webkit-details-marker,
.public-menu summary::-webkit-details-marker {
  display: none;
}

.account-menu summary::marker,
.public-menu summary::marker {
  content: '';
}

.account-menu__sheet {
  position: absolute;
  inset-block-start: calc(100% + var(--space-2));
  inset-inline-end: 0;
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-modal);
  min-inline-size: 200px;
  padding: var(--space-2);
  z-index: 20;
  display: flex;
  flex-direction: column;
}

.account-menu__link {
  display: block;
  inline-size: 100%;
  text-align: start;
  padding: var(--space-3);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-body);
  border-radius: var(--radius-sm);
  transition: background var(--duration-quick) var(--easing-default);
}

.account-menu__link:hover {
  background: var(--accent-weekly-bg);
  color: var(--text-body);
}

.account-menu__link--destructive {
  color: var(--color-error);
}

.account-menu form {
  margin: 0;
}

/* Public-menu (hamburger) sheet — same shape as the account-menu
 * sheet so the dropdown shell is consistent across both states. */
.public-menu__sheet {
  position: absolute;
  inset-block-start: calc(100% + var(--space-2));
  inset-inline-end: 0;
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-modal);
  min-inline-size: 180px;
  padding: var(--space-2);
  z-index: 20;
  display: flex;
  flex-direction: column;
}

.public-menu__link {
  display: block;
  inline-size: 100%;
  text-align: start;
  padding: var(--space-3);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-body);
  border-radius: var(--radius-sm);
  transition: background var(--duration-quick) var(--easing-default);
  background: transparent;
  border: 0;
  cursor: pointer;
}

.public-menu__link:hover {
  background: var(--accent-weekly-bg);
}

.public-menu__link--primary {
  font-weight: 600;
}

/* Bottom tab bar (mobile only) */
.bottom-tab-bar {
  display: flex;
  position: fixed;
  inset-block-end: 0;
  inset-inline: 0;
  background: color-mix(in oklab, var(--bg-page) 90%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-block-start: 1px solid var(--border-subtle);
  z-index: 10;
}

@media (min-width: 768px) {
  .bottom-tab-bar {
    display: none;
  }
}

.bottom-tab-bar__link {
  flex: 1;
  text-align: center;
  padding: var(--space-3) var(--space-2);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  transition: color var(--duration-quick) var(--easing-default);
}

.bottom-tab-bar__link.is-active {
  color: var(--text-body);
}

/* Body padding when bottom tab bar is present */
body:has(.bottom-tab-bar) {
  padding-block-end: 64px;
}

@media (min-width: 768px) {
  body:has(.bottom-tab-bar) {
    padding-block-end: 0;
  }
}

/* Marketing-only anchor links — hide on mobile. The default
 * .app-header__nav already drops the whole nav under 768px (mobile
 * uses the bottom tab bar instead), but we keep this rule so the
 * class is honest about its mobile behavior even if the nav-level
 * hiding ever changes. */
.app-header__nav-link--anchor {
  display: none;
}

@media (min-width: 768px) {
  .app-header__nav-link--anchor {
    display: inline-flex;
  }
}

/* Mobile: collapse the inline action buttons into the dropdown menus.
 * The theme toggle, Log in, and Sign up all live inside .account-menu
 * (authed) or .public-menu (unauthed) on small screens so the header
 * stays uncluttered. The dropdown summaries — avatar and hamburger
 * — are kept visible. */
@media (max-width: 767.98px) {
  .app-header__actions > .theme-icon-button,
  .app-header__actions > .app-header__nav-link {
    display: none;
  }
}

/* Tablet+: the inline actions are visible, so the mobile-only
 * hamburger menu and the in-dropdown Theme line both collapse to
 * avoid duplication. */
@media (min-width: 768px) {
  .public-menu,
  .account-menu__link--theme {
    display: none;
  }
}

/* Icon-only theme toggle. Lives in the actions zone (both authed
 * and unauthed). Two SVGs render in the DOM; CSS toggles which is
 * visible based on the active theme — moon means click → dark,
 * sun means click → light. */
.theme-icon-button {
  display: grid;
  place-items: center;
  inline-size: 36px;
  block-size: 36px;
  border-radius: 50%;
  background: transparent;
  border: 1px solid var(--border-subtle);
  color: var(--text-muted);
  cursor: pointer;
  flex-shrink: 0;
  transition:
    color var(--duration-quick) var(--easing-default),
    border-color var(--duration-quick) var(--easing-default),
    background var(--duration-quick) var(--easing-default);
}

.theme-icon-button:hover {
  color: var(--text-body);
  border-color: var(--text-muted);
  background: var(--bg-card);
}

.theme-icon-button svg {
  inline-size: 18px;
  block-size: 18px;
  stroke: currentColor;
  stroke-width: 1.5;
  fill: none;
  stroke-linejoin: round;
}

/* Default: moon visible (click goes to dark). */
.theme-icon-button .icon-sun {
  display: none;
}

.theme-icon-button .icon-moon {
  display: block;
}

/* Dark active via system preference (and not overridden to light). */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .theme-icon-button .icon-sun {
    display: block;
  }

  :root:not([data-theme='light']) .theme-icon-button .icon-moon {
    display: none;
  }
}

/* Dark active via explicit manual override. */
[data-theme='dark'] .theme-icon-button .icon-sun {
  display: block;
}

[data-theme='dark'] .theme-icon-button .icon-moon {
  display: none;
}

.app-header__nav-link--cta {
  background: var(--text-body);
  color: var(--bg-page);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  font-weight: 500;
  transition: opacity var(--duration-quick) var(--easing-default);
}

.app-header__nav-link--cta:hover {
  color: var(--bg-page);
  opacity: 0.85;
}

/* ==========================================================================
   Buttons & form controls
   ========================================================================== */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  font-family: var(--font-body-sans);
  font-size: var(--text-base);
  font-weight: 500;
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition:
    background var(--duration-quick) var(--easing-default),
    color var(--duration-quick) var(--easing-default),
    transform var(--duration-quick) var(--easing-default),
    box-shadow var(--duration-quick) var(--easing-default);
  border: 1px solid transparent;
  text-decoration: none;
}

.button--primary {
  background: var(--text-body);
  color: var(--bg-page);
}

.button--primary:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-card);
}

.button--secondary {
  background: transparent;
  color: var(--text-body);
  border-color: var(--border-subtle);
}

.button--secondary:hover {
  border-color: var(--text-muted);
  background: var(--bg-card);
}

.button--ghost {
  background: transparent;
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  padding: var(--space-2) var(--space-3);
}

.button--ghost:hover {
  color: var(--text-body);
}

.button--destructive {
  background: transparent;
  color: var(--color-error);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  padding: var(--space-2) var(--space-3);
}

/* Loading state — the button itself becomes the activity indicator while a
   slow action runs (e.g. card capture + server confirm on the trial/billing
   screens): label swaps to "Processing" plus three bouncing dots. Applied by
   revolut-widget.js together with disabled + aria-busy. The dots ride the
   chat-typing-bounce keyframes (defined with the chat typing indicator). */
.button--loading {
  cursor: default;
}

.button--loading:hover {
  transform: none;
  box-shadow: none;
}

.button__dot {
  inline-size: 6px;
  block-size: 6px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.4;
  animation: chat-typing-bounce 1.2s infinite ease-in-out;
}

.button__dot:nth-child(2) { animation-delay: 0.15s; }
.button__dot:nth-child(3) { animation-delay: 0.30s; }

@media (prefers-reduced-motion: reduce) {
  .button__dot { animation: none; opacity: 0.7; }
}

.button-row {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  margin-block-start: var(--space-5);
  flex-wrap: wrap;
}

.button-row--end {
  justify-content: flex-end;
}

.button-row--center {
  justify-content: center;
}

/* Form fields */
.form-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-block: var(--space-5);
}

.form-label {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
}

.form-input,
.form-textarea,
.form-select {
  padding: var(--space-3) var(--space-4);
  font-family: var(--font-body-sans);
  font-size: var(--text-md);
  background: var(--bg-card);
  color: var(--text-body);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  transition: border-color var(--duration-quick) var(--easing-default);
  /* Without these, flex-item min-inline-size: auto + the input's
   * intrinsic size="20" width forces the form (and its containing
   * card) wider than narrow viewports, overflowing horizontally.
   * Letting the input shrink to its container is the fix. */
  inline-size: 100%;
  min-inline-size: 0;
}

.form-input--large {
  font-family: var(--font-body-sans);
  font-size: var(--text-lg);
  font-weight: 500;
  padding: var(--space-4) var(--space-4);
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  /* Stronger affordance than the default field — the most important
     input on the page deserves a visible container without reading
     as a display title. */
}

.form-input:focus,
.form-textarea:focus,
.form-select:focus {
  outline: none;
  border-color: var(--text-muted);
}

.form-input--large:focus {
  border-color: var(--text-body);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--text-body) 8%, transparent);
}

/* All input placeholders render in italic + faint so hint text is
   unmistakable. The italic flag also makes example strings
   ("e.g. \"EU AI regulation\"") read as examples, not as user content
   that was already typed. */
.form-input::placeholder,
.form-input--large::placeholder,
.form-textarea::placeholder {
  font-style: italic;
  color: var(--text-faint);
}

.form-textarea {
  font-family: var(--font-body-serif);
  line-height: var(--leading-relaxed);
  resize: vertical;
  min-block-size: 96px;
}

/* Email-verification code input — a single monospace, letter-spaced field
   that visually rhymes with the code block in the verification email
   (`.email__panel-code`), so the code the reader copies looks the same in
   both places. See apps/web/templates/welcome_verify.html. */
.verify-code-field {
  display: block;
  inline-size: 100%;
  box-sizing: border-box;
  font-family: 'SF Mono', 'Menlo', 'Consolas', monospace;
  font-size: var(--text-3xl);
  font-weight: 600;
  letter-spacing: 0.3em;
  text-align: center;
  color: var(--text-body);
  background: var(--bg-page);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-3);
  caret-color: var(--text-body);
}

.verify-code-field::placeholder {
  color: var(--border-subtle);
  letter-spacing: 0.3em;
}

.verify-code-field:focus {
  outline: none;
  border-color: var(--text-body);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--text-body) 12%, transparent);
}

.verify-code-field.is-error {
  border-color: var(--color-error);
}

.form-helper {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.form-error {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--color-error);
  margin-block-start: var(--space-2);
}

/* Inline field-error border — pairs with the `.form-error` message beneath a
 * field on /signup and /reset-password (driven by static/password-strength.js
 * client-side, pre-filled server-side from `field_errors`). Mirrors the
 * verify-code-field treatment above so an at-fault field reads as wrong
 * without a native browser tooltip (invisible on mobile). */
.form-input.is-error,
.form-textarea.is-error,
.form-select.is-error {
  border-color: var(--color-error);
}

/* Password strength meter — sits under the password field on /signup and
   /reset-password (template partial _password_strength.html, driven by
   static/password-strength.js). A four-segment bar + one calm hint line,
   hidden until the user types. Filled segments recolour and drop their
   hairline; unfilled segments stay empty track — like the credit meter, where
   unfilled reads as room left. Red while the policy is unmet, sage once it
   passes. */
.pw-strength {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-block-start: var(--space-2);
}

.pw-strength__track {
  display: flex;
  gap: var(--space-1);
}

.pw-strength__seg {
  flex: 1;
  block-size: 4px;
  background: var(--bg-page);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  transition: background var(--duration-quick) var(--easing-default),
              border-color var(--duration-quick) var(--easing-default);
}

.pw-strength[data-level="1"] .pw-strength__seg:nth-child(-n+1),
.pw-strength[data-level="2"] .pw-strength__seg:nth-child(-n+2),
.pw-strength[data-level="3"] .pw-strength__seg:nth-child(-n+3),
.pw-strength[data-level="4"] .pw-strength__seg:nth-child(-n+4) {
  border-color: transparent;
}
.pw-strength[data-level="1"] .pw-strength__seg:nth-child(-n+1) { background: var(--color-error); }
.pw-strength[data-level="2"] .pw-strength__seg:nth-child(-n+2) { background: var(--color-warning); }
.pw-strength[data-level="3"] .pw-strength__seg:nth-child(-n+3) { background: var(--color-success); }
.pw-strength[data-level="4"] .pw-strength__seg:nth-child(-n+4) { background: var(--color-success); }

.pw-strength__hint {
  margin: 0;
  min-block-size: 1.1em; /* reserve the line so layout never jumps */
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  line-height: var(--leading-snug);
  color: var(--text-muted);
}
.pw-strength[data-level="1"] .pw-strength__hint { color: var(--color-error); }
.pw-strength[data-level="2"] .pw-strength__hint { color: var(--color-warning); }
.pw-strength[data-level="3"] .pw-strength__hint,
.pw-strength[data-level="4"] .pw-strength__hint { color: var(--color-success); }

/* Radio + checkbox groups */
.radio-group,
.checkbox-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* Block layout (not flex) so multi-line label content flows as one
 * inline-formatting context. Flex made every text node and anchor a
 * separate flex item that wrapped internally — producing a broken
 * "I agree to / the / Terms & / Conditions" stack on the /signup
 * terms acknowledgement (settings checkboxes never showed it because
 * their labels are a single short phrase). */
.radio-option,
.checkbox-option {
  display: block;
  position: relative;
  /* Reserve the gutter the absolute-positioned input sits in
   * (input width + the gap that --space-3 used to provide). */
  padding-inline-start: calc(18px + var(--space-3));
  font-family: var(--font-body-sans);
  font-size: var(--text-md);
  /* Fixed 24px (not a relative leading token) so the line-box is tall
   * enough to contain the 18px absolutely-positioned checkbox with
   * breathing room on either side, regardless of variant font-size.
   * The 0.15em top offset on the input then lands the box visually
   * aligned with the cap-height of the first line. */
  line-height: 24px;
  cursor: pointer;
}

.radio-option input,
.checkbox-option input {
  position: absolute;
  inset-inline-start: 0;
  /* Center the 18px box in the first-line line-box: (24-18)/2 = 3px.
   * Using `1lh` (resolved line-height of the parent label) keeps the
   * math correct if the label line-height ever changes — works for
   * both the regular and the --quiet variant. */
  inset-block-start: calc((1lh - 18px) / 2);
  inline-size: 18px;
  block-size: 18px;
}

/* Radio buttons keep native rendering — accent-color drives the checked
 * fill. (Checkboxes can't use accent-color because we render them custom
 * below to control the unchecked border colour.) */
.radio-option input {
  accent-color: var(--text-body);
}

.radio-option input:focus-visible,
.checkbox-option input:focus-visible {
  /* Soft 3px wash on focus — same treatment as .form-input--large:focus.
   * The wash is tinted by --text-body at 12%, adapts to both modes via
   * color-mix. */
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--text-body) 12%, transparent);
}

/* Forced-colors / Windows high-contrast: box-shadow is suppressed,
 * so reinstate a visible outline to honour the accessibility floor
 * (design-tokens.md: focus rings visible on all interactive elements). */
@media (forced-colors: active) {
  .radio-option input:focus-visible,
  .checkbox-option input:focus-visible {
    outline: 2px solid CanvasText;
    outline-offset: 2px;
  }
}

/* Custom-drawn checkbox so the unchecked border matches form-input
 * (--border-subtle) rather than the heavier browser-default gray.
 * Border-radius is 4px (not --radius-sm / 8px) because 8px on an 18px
 * box reads as a near-pill; 4px is the proportional match to the form
 * inputs' 8px-on-44px. */
.checkbox-option input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  border: 1px solid var(--border-subtle);
  border-radius: 4px;
  background-color: var(--bg-card);
  transition:
    border-color var(--duration-quick) var(--easing-default),
    background-color var(--duration-quick) var(--easing-default),
    box-shadow var(--duration-quick) var(--easing-default);
}

.checkbox-option input[type="checkbox"]:hover:not(:disabled) {
  border-color: var(--text-muted);
}

/* Light mode (default) — substrate-warm check on dark fill, with a
 * 1-px tactile lift to signal "confirmed". Stroke is --bg-page (warm
 * cream) for editorial coherence; stroke-width 2 is a deliberate
 * compromise between the design-tokens icon spec (~0.9px scaled) and
 * the heavier proportions traditional check icons need to read at
 * small sizes. */
.checkbox-option input[type="checkbox"]:checked {
  background-color: var(--text-body);
  border-color: var(--text-body);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23FAF7F2' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M4 8.5 7 11.5 12.5 5'/></svg>");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 12px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
}

/* Dark mode (system or manual) — substrate-charcoal check on warm
 * off-white fill, no shadow (design-tokens: dark elevation comes from
 * bg-color shifts, not shadows). Both selectors required to match
 * the project's dual-control pattern (see .theme-icon-button). */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .checkbox-option input[type="checkbox"]:checked {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%231A1816' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M4 8.5 7 11.5 12.5 5'/></svg>");
    box-shadow: none;
  }
}

[data-theme='dark'] .checkbox-option input[type="checkbox"]:checked {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%231A1816' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M4 8.5 7 11.5 12.5 5'/></svg>");
  box-shadow: none;
}

/* Quiet variant: legal acknowledgements and similar supporting-copy
 * acceptance rows (e.g. Terms & Privacy on /signup). Reads as helper
 * text — small, serif, muted — not as a primary control. Upright (not
 * italic) so legal copy reads serious. The checkbox itself keeps its
 * standard 18px size for hit-target parity. */
.checkbox-option--quiet {
  font-family: var(--font-body-serif);
  font-size: var(--text-sm);
  color: var(--text-muted);
}

/* Inline links inside an acceptance label (e.g. Terms / Privacy on the
 * signup page) — match the editorial underline used by .auth-card__alt a
 * rather than inheriting the browser-default blue/purple link. */
.checkbox-option a {
  color: var(--text-body);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

.checkbox-option a:hover {
  text-decoration-thickness: 2px;
}

.radio-option__hint,
.checkbox-option__hint {
  color: var(--text-muted);
  font-style: italic;
  font-size: var(--text-sm);
}

.radio-option:has(input:disabled),
.checkbox-option:has(input:disabled) {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ==========================================================================
   Settings card / settings groups
   ========================================================================== */

.settings-card {
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  padding: var(--space-6);
  box-shadow: var(--shadow-card);
  margin-block: var(--space-5);
}

/* Mobile: the page gutter and the card's own padding stack on the left
   and right, double-squeezing content on narrow screens (e.g. the
   weekday pill row wrapping). Trim the card's horizontal padding on
   small screens — the page gutter already supplies the outer breathing
   room — and ease the vertical padding to match. */
@media (max-width: 767px) {
  .settings-card {
    padding: var(--space-5) var(--space-4);
  }
}

.settings-card[data-cadence='daily'] {
  background: color-mix(in oklab, var(--bg-card) 95%, var(--accent-daily) 5%);
}

.settings-card[data-cadence='weekly'] {
  background: color-mix(in oklab, var(--bg-card) 95%, var(--accent-weekly) 5%);
}

.settings-card[data-cadence='monthly'] {
  background: color-mix(in oklab, var(--bg-card) 95%, var(--accent-monthly) 5%);
}

.settings-card__group {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.settings-card__group + .settings-card__group {
  margin-block-start: var(--space-5);
  padding-block-start: var(--space-5);
  border-block-start: 1px solid var(--border-subtle);
}

/* Group-separator across a <form> boundary. The adjacent-sibling rule
   above can't see across a <form> that wraps the lower groups (e.g. the
   notifications form below the Web Push enrol block), so its first group
   loses the hairline + spacing and butts against the control above.
   Restore it when the form isn't the card's first child. */
.settings-card > form:not(:first-child) > .settings-card__group:first-child {
  margin-block-start: var(--space-5);
  padding-block-start: var(--space-5);
  border-block-start: 1px solid var(--border-subtle);
}

.settings-card__group-label {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
  margin-block-end: var(--space-2);
}

/* ── Plan & billing tab ───────────────────────────────────────────── */

/* "Your plan" line — display-serif plan name, faint allowance context. */
.plan-summary {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.plan-summary__name {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  font-variation-settings: 'opsz' 36;
}

.plan-summary__price {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-faint);
}

/* Deferred-billing affordances — visible-but-disabled rows that name
   what payment management will add, without faking the flow. */
.deferred-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding-block: var(--space-3);
}

.deferred-row + .deferred-row {
  border-block-start: 1px solid var(--border-subtle);
}

.deferred-row__label {
  font-family: var(--font-body-sans);
  font-size: var(--text-md);
  color: var(--text-muted);
}

.deferred-row__pill {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
  background: var(--bg-page);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  padding: 2px var(--space-3);
  white-space: nowrap;
}

/* ── Profile tab — danger zone + legal ────────────────────────────── */

.settings-card--danger {
  border-color: color-mix(in oklab, var(--color-error) 30%, var(--border-subtle));
}

.settings-card__danger-title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  color: var(--color-error);
  margin: 0 0 var(--space-2);
}

.button--danger {
  background: var(--color-error);
  color: #fff;
  border-color: transparent;
}

.button--danger:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-card);
}

/* Status pill */
.status-pill {
  display: inline-flex;
  align-items: center;
  padding: 2px var(--space-3);
  border-radius: var(--radius-pill);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  background: var(--accent-weekly-bg);
  color: var(--text-body);
}

.status-pill--paused {
  background: var(--bg-card);
  color: var(--text-muted);
  border: 1px solid var(--border-subtle);
}

/* ==========================================================================
   Modal — native <dialog>, opened via showModal()
   ========================================================================== */

.modal {
  margin: auto;
  inline-size: 100%;
  max-inline-size: 420px;
  padding: var(--space-6);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  background: var(--bg-card);
  color: var(--text-body);
  box-shadow: var(--shadow-modal);
}

.modal::backdrop {
  background: color-mix(in oklab, var(--bg-page) 60%, #000);
}

.modal__eyebrow {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
  margin-block-end: var(--space-2);
}

.modal__title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 700;
  margin-block-end: var(--space-3);
}

.modal__body {
  font-family: var(--font-body-serif);
  font-style: italic;
  color: var(--text-muted);
  margin-block-end: var(--space-5);
}

.modal__actions {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  justify-content: flex-end;
}

/* Legal variant — a tall, scrollable dialog for long-form legal prose shown in
   place (the onboarding consent → Terms modal). Header and the Done action stay
   fixed; only the prose between them scrolls. */
.modal--legal {
  max-inline-size: min(640px, 92vw);
  max-block-size: 85vh;
}

/* Gate the flex layout on the open state. A bare `display: flex` here would be
   an author rule that beats the UA `dialog:not([open]) { display: none }`,
   leaving the dialog rendered in page flow and impossible to close (`.close()`
   only toggles `[open]`). Scoping to `[open]` lets the UA hide it when shut. */
.modal--legal[open] {
  display: flex;
  flex-direction: column;
}

.modal__legal-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  margin-block-end: var(--space-4);
}

.modal__legal-head .modal__title {
  margin-block-end: 0;
}

.modal__close {
  flex-shrink: 0;
  font-size: var(--text-xl);
  line-height: 1;
  color: var(--text-muted);
  padding: var(--space-1);
  transition: color var(--duration-quick) var(--easing-default);
}

.modal__close:hover {
  color: var(--text-body);
}

/* The scroll region grows to fill the dialog and scrolls its overflow;
   min-block-size:0 lets it actually shrink inside the flex column. */
.modal__scroll {
  flex: 1 1 auto;
  min-block-size: 0;
  overflow-y: auto;
  margin-block-end: var(--space-5);
}

/* ==========================================================================
   Topic card
   ========================================================================== */

.topic-card {
  display: block;
  position: relative;
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: var(--space-5) var(--space-5) var(--space-5) var(--space-6);
  box-shadow: var(--shadow-card);
  transition:
    transform var(--duration-quick) var(--easing-default),
    box-shadow var(--duration-quick) var(--easing-default);
}

.topic-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-card-hover);
}

.topic-card::before {
  content: '';
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  inline-size: 3px;
  background: var(--accent-strip, var(--accent-weekly));
  border-start-start-radius: var(--radius-md);
  border-end-start-radius: var(--radius-md);
}

@media (min-width: 1024px) {
  .topic-card::before {
    inset-inline-start: -16px;
    border-radius: var(--radius-pill);
  }
}

.topic-card[data-cadence='daily'] {
  --accent-strip: var(--accent-daily);
}

.topic-card[data-cadence='weekly'] {
  --accent-strip: var(--accent-weekly);
}

.topic-card[data-cadence='monthly'] {
  --accent-strip: var(--accent-monthly);
}

.topic-card.is-paused {
  opacity: 0.55;
}

.topic-card__title {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
  margin-block: var(--space-2);
  font-variation-settings: 'opsz' 36;
}

.topic-card__description {
  font-family: var(--font-body-serif);
  font-size: var(--text-base);
  color: var(--text-muted);
  line-height: var(--leading-relaxed);
  margin-block-end: var(--space-3);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.topic-card__meta {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  color: var(--text-faint);
  text-transform: uppercase;
}

/* ==========================================================================
   Page header (used on /topics, /bookmarks, /settings)
   ========================================================================== */

.page-header {
  margin-block: var(--space-7) var(--space-6);
  padding-inline-start: var(--space-3);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
}

/* Editorial drop-indent on tablet+ — same value as `.drop-indent` and
 * `.greeting` so page titles read as a deliberate signature rather than
 * misalignment with the content underneath. */
@media (min-width: 768px) {
  .page-header {
    padding-inline-start: var(--space-7);
  }
}

.page-header__title {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 600;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  font-variation-settings: 'opsz' 96;
}

@media (min-width: 768px) {
  .page-header__title {
    font-size: var(--text-4xl);
  }
}

.page-header__subtitle {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  font-style: italic;
  color: var(--text-muted);
  margin-block-start: var(--space-2);
}

/* "Next brief lands …" line under a topic title. */
.page-header__arrival {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  font-style: italic;
  color: var(--text-muted);
  margin-block-start: var(--space-4);
}

.page-header__actions {
  display: flex;
  gap: var(--space-3);
}

/* ==========================================================================
   Tab nav (typographic divider style)
   ========================================================================== */

.tab-nav {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-block: var(--space-6);
  padding-block-end: var(--space-3);
  border-block-end: 1px solid var(--border-subtle);
}

.tab-nav__separator {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  color: var(--text-faint);
}

.tab-nav__link {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-lg);
  color: var(--text-muted);
  transition: color var(--duration-quick) var(--easing-default);
}

.tab-nav__link.is-active {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 700;
  color: var(--text-body);
  font-variation-settings: 'opsz' 24;
}

.tab-nav__link:hover {
  color: var(--text-body);
}

/* Mobile: the three serif tabs don't fit on one line at the desktop type
   size, and "Plan & billing" was breaking at its space. Drop the tab
   type a step on small screens so all three sit on one line (fits down
   to ~320px); keep labels whole with nowrap, and flex-wrap as a
   whole-tab fallback for anything tinier. Desktop is left exactly as-is. */
@media (max-width: 767px) {
  .tab-nav {
    flex-wrap: wrap;
  }
  .tab-nav__link {
    white-space: nowrap;
    font-size: var(--text-base);
  }
  .tab-nav__separator {
    font-size: var(--text-md);
  }
}

/* ==========================================================================
   Empty state
   ========================================================================== */

.empty-state {
  text-align: center;
  padding: var(--space-9) var(--space-5);
  margin-block: var(--space-7);
}

.empty-state__title {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 600;
  color: var(--text-muted);
  margin-block-end: var(--space-3);
  font-variation-settings: 'opsz' 72;
}

.empty-state__body {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  color: var(--text-muted);
  font-style: italic;
  max-inline-size: 40ch;
  margin-inline: auto;
  margin-block-end: var(--space-5);
}

.empty-state__panel {
  max-inline-size: 480px;
  margin-inline: auto;
  block-size: 200px;
  border-radius: var(--radius-xl);
  background:
    radial-gradient(ellipse at 30% 20%, var(--accent-weekly-bg) 0%, transparent 60%),
    radial-gradient(ellipse at 80% 80%, var(--accent-daily-bg) 0%, transparent 60%),
    var(--bg-card);
  filter: blur(0.5px);
}

/* --- Editorial variant --------------------------------------------------
 * Used on /feed when there are no briefs yet. Drops the gradient slab in
 * favour of a typeset editorial note: ornament rule on top, display title
 * + italic standfirst in the middle, sign-off rule on bottom. The sign-off
 * components below (`.sign-off--ornament`, `.sign-off--soft`) carry the
 * rules; this modifier just tightens the surrounding rhythm. */
.empty-state--editorial {
  padding-block: var(--space-7);
}

.empty-state--editorial .empty-state__title {
  color: var(--text-body);
  font-size: var(--text-3xl);
  margin-block: var(--space-2) var(--space-4);
}

@media (min-width: 768px) {
  .empty-state--editorial .empty-state__title {
    font-size: var(--text-4xl);
  }
}

.empty-state--editorial .empty-state__body {
  line-height: var(--leading-relaxed);
  margin-block-end: 0;
}

.empty-state--editorial .empty-state__body strong {
  font-style: normal;
  font-weight: 500;
  color: var(--text-body);
}

.empty-state__cta {
  margin-block-start: var(--space-6);
}

/* ==========================================================================
   Auth (login / signup)
   ========================================================================== */

.auth-page {
  min-block-size: 100vh;
  display: grid;
  place-items: center;
  /* Mobile: tight horizontal frame so the card sits well within
   * narrow viewports. Tablet+ restores the original generous gutter. */
  padding: var(--space-6) var(--space-4);
  background:
    radial-gradient(ellipse at 20% 0%, var(--accent-weekly-bg) 0%, transparent 50%),
    radial-gradient(ellipse at 100% 100%, var(--accent-daily-bg) 0%, transparent 50%),
    var(--bg-page);
}

@media (min-width: 768px) {
  .auth-page {
    padding: var(--space-7) var(--space-5);
  }
}

.auth-card {
  max-inline-size: var(--container-narrow);
  inline-size: 100%;
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  /* Mobile: tighter inner padding so the form has room to breathe
   * inside the card. Tablet+ restores the editorial padding. */
  padding: var(--space-6) var(--space-5);
  box-shadow: var(--shadow-card-hover);
}

@media (min-width: 768px) {
  .auth-card {
    padding: var(--space-7) var(--space-6);
  }
}

.auth-card__title {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  margin-block-end: var(--space-2);
  font-variation-settings: 'opsz' 72;
}

.auth-card__lede {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  color: var(--text-muted);
  font-style: italic;
  margin-block-end: var(--space-6);
}

.auth-card__alt {
  margin-block-start: var(--space-5);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
  text-align: center;
}

.auth-card__alt a {
  color: var(--text-body);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.auth-card__error {
  background: color-mix(in oklab, var(--color-error) 10%, transparent);
  color: var(--color-error);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  margin-block-end: var(--space-5);
}

/* "Continue with Google" — a full-width secondary button with the brand mark. */
.auth-google {
  inline-size: 100%;
}

.auth-google__icon {
  flex: none;
}

.auth-google__terms {
  margin-block-start: var(--space-3);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  color: var(--text-muted);
  text-align: center;
}

.auth-google__terms a {
  color: var(--text-muted);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* The "or" divider between Google sign-in and the email form. A hairline rule
 * with the label sitting in a gap, centred. */
.auth-divider {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-block: var(--space-5);
  color: var(--text-muted);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.auth-divider::before,
.auth-divider::after {
  content: "";
  flex: 1;
  block-size: 1px;
  background: var(--border-subtle);
}

/* ==========================================================================
   Marketing (landing)
   ========================================================================== */

.marketing-hero {
  position: relative;
  /* Mobile: tighter top + bottom padding so the dictionary entry
   * surfaces above the fold. Tablet+ restores the original
   * generous editorial breathing room. */
  padding: var(--space-6) var(--space-5) var(--space-7);
  overflow: hidden;
  isolation: isolate;
}

@media (min-width: 768px) {
  .marketing-hero {
    padding: var(--space-9) var(--space-5) var(--space-10);
  }
}

.marketing-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse at 80% 0%, var(--accent-weekly-bg) 0%, transparent 60%),
    radial-gradient(ellipse at 0% 70%, var(--accent-daily-bg) 0%, transparent 50%),
    radial-gradient(ellipse at 60% 100%, var(--accent-monthly-bg) 0%, transparent 50%);
  z-index: -1;
  filter: blur(8px);
}

.marketing-hero__content {
  max-inline-size: var(--container-reading);
  margin-inline: auto;
}

.marketing-hero__eyebrow {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-block-end: var(--space-4);
}

.marketing-hero__headline {
  font-family: var(--font-display);
  /* Mobile: text-4xl keeps the hero feeling commanding without forcing
   * 5+ line wraps that push the lede below the fold. The three-tier
   * ramp below restores the original scale on tablet and desktop. */
  font-size: var(--text-4xl);
  font-weight: 700;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  margin-block-end: var(--space-5);
  font-variation-settings: 'opsz' 144;
  margin-inline-start: var(--space-3);
}

@media (min-width: 768px) {
  .marketing-hero__headline {
    font-size: var(--text-5xl);
    margin-inline-start: var(--space-7);
  }
}

@media (min-width: 1024px) {
  .marketing-hero__headline {
    font-size: var(--text-6xl);
  }
}

.marketing-hero__lede {
  font-family: var(--font-body-serif);
  font-size: var(--text-xl);
  line-height: var(--leading-relaxed);
  color: var(--text-body);
  max-inline-size: 50ch;
  margin-block-end: var(--space-6);
}

/* Dictionary-entry variant of the hero lede. Reframes the product
 * description as a definition: bold display headword, IPA pronunciation,
 * italic part-of-speech marker, definition body, italic usage note. */
.marketing-hero__lede--entry {
  max-inline-size: 56ch;
}

.marketing-hero__lede .entry__headword {
  font-family: var(--font-display);
  font-weight: 700;
  font-style: normal;
  color: var(--text-body);
  font-variation-settings: 'opsz' 32;
  margin-inline-end: var(--space-1);
}

.marketing-hero__lede .entry__pronunciation {
  font-family: var(--font-body-serif);
  font-style: normal;
  color: var(--text-muted);
  font-size: 0.9em;
  margin-inline-end: var(--space-2);
}

.marketing-hero__lede .entry__pos {
  font-family: var(--font-body-serif);
  font-style: italic;
  color: var(--text-muted);
  margin-inline-end: var(--space-2);
}

.marketing-hero__lede .entry__usage {
  font-family: var(--font-body-serif);
  font-style: italic;
  color: var(--text-muted);
}

.marketing-section {
  padding: var(--space-9) var(--space-5);
  max-inline-size: var(--container-reading);
  margin-inline: auto;
}

.marketing-section__title {
  font-family: var(--font-display);
  font-size: var(--text-4xl);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  margin-block-end: var(--space-7);
  font-variation-settings: 'opsz' 96;
}

.step-list {
  display: grid;
  gap: var(--space-6);
}

@media (min-width: 768px) {
  .step-list {
    grid-template-columns: repeat(3, 1fr);
  }
}

.step-block {
  position: relative;
  padding: var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  overflow: hidden;
  isolation: isolate;
}

.step-block::before {
  content: '';
  position: absolute;
  inset-block-start: -50%;
  inset-inline-end: -30%;
  inline-size: 70%;
  aspect-ratio: 1;
  background: radial-gradient(circle, var(--step-tint, var(--accent-weekly-bg)) 0%, transparent 70%);
  border-radius: 50%;
  filter: blur(20px);
  opacity: 0.7;
  z-index: -1;
}

.step-block:nth-child(1) {
  --step-tint: var(--accent-daily-bg);
}

.step-block:nth-child(2) {
  --step-tint: var(--accent-weekly-bg);
}

.step-block:nth-child(3) {
  --step-tint: var(--accent-monthly-bg);
}

.step-block__number {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
  margin-block-end: var(--space-3);
}

.step-block__title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  line-height: var(--leading-snug);
  margin-block-end: var(--space-3);
  font-variation-settings: 'opsz' 30;
}

.step-block__body {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
}

/* Principles — editorial-grade Features section. Lead pull-quote
 * highlights the most distinctive trait; remaining traits sit in a
 * typographic grid with italic Fraunces letter marks tinted by
 * cadence. No card chrome — the typography does the visual work. */
.principles__lead {
  margin-block: var(--space-7) var(--space-8);
  padding-inline-start: var(--space-5);
  border-inline-start: 2px solid var(--accent-weekly);
  max-inline-size: 64ch;
}

.principles__lead-text {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-xl);
  line-height: var(--leading-relaxed);
  color: var(--text-body);
}

@media (min-width: 768px) {
  .principles__lead-text {
    font-size: var(--text-2xl);
  }
}

.principles__lead-byline {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-block-start: var(--space-4);
}

.principles {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6) var(--space-6);
  padding-block-start: var(--space-7);
  border-block-start: 1px solid var(--border-subtle);
}

@media (min-width: 768px) {
  .principles {
    grid-template-columns: repeat(2, 1fr);
    column-gap: var(--space-7);
    row-gap: var(--space-7);
  }
}

@media (min-width: 1024px) {
  .principles {
    grid-template-columns: repeat(3, 1fr);
  }
}

.principle {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: var(--space-4);
  align-items: baseline;
}

.principle__mark {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: var(--text-4xl);
  line-height: 1;
  color: var(--principle-mark-color, var(--text-faint));
  font-variation-settings: 'opsz' 96;
  /* Reserve a consistent gutter so the title column starts at the
   * same x across all rows regardless of which letter is in the mark. */
  min-inline-size: 32px;
}

.principle[data-cadence='daily'] {
  --principle-mark-color: var(--accent-daily);
}

.principle[data-cadence='weekly'] {
  --principle-mark-color: var(--accent-weekly);
}

.principle[data-cadence='monthly'] {
  --principle-mark-color: var(--accent-monthly);
}

.principle__title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
  margin-block-end: var(--space-2);
  color: var(--text-body);
  font-variation-settings: 'opsz' 30;
}

.principle__body {
  font-family: var(--font-body-serif);
  font-size: var(--text-base);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
}

/* Closing invitation. Reads as an editor's note rather than a CTA
 * card — cadence-tinted gradient backdrop with a soft abstract shape,
 * display headline, italic body, and an optional sign-off line below
 * the buttons mirroring the brief sign-off pattern. */
.cta-block {
  position: relative;
  padding: var(--space-8) var(--space-6);
  background:
    radial-gradient(ellipse at 75% 0%, var(--accent-weekly-bg) 0%, transparent 60%),
    radial-gradient(ellipse at 10% 100%, var(--accent-daily-bg) 0%, transparent 55%),
    var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  text-align: center;
  margin-inline: auto;
  max-inline-size: var(--container-content);
  isolation: isolate;
  overflow: hidden;
}

@media (min-width: 768px) {
  .cta-block {
    padding: var(--space-9) var(--space-7);
  }
}

.cta-block::before {
  content: '';
  position: absolute;
  inset-block-start: -40%;
  inset-inline-end: -15%;
  inline-size: 60%;
  aspect-ratio: 1;
  background: radial-gradient(
    circle,
    color-mix(in oklab, var(--accent-weekly) 30%, transparent) 0%,
    transparent 70%
  );
  border-radius: 60% 40% 70% 30% / 50% 60% 40% 50%;
  filter: blur(40px);
  opacity: 0.7;
  z-index: -1;
  pointer-events: none;
}

.cta-block__eyebrow {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-block-end: var(--space-4);
}

.cta-block__title {
  font-family: var(--font-display);
  font-size: var(--text-4xl);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-tight);
  margin-block-end: var(--space-4);
  font-variation-settings: 'opsz' 144;
  max-inline-size: 24ch;
  margin-inline: auto;
}

@media (min-width: 768px) {
  .cta-block__title {
    font-size: var(--text-5xl);
  }
}

.cta-block__body {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
  margin-block-end: var(--space-6);
  max-inline-size: 50ch;
  margin-inline: auto;
}

/* Italic sign-off line — mirrors the brief detail page's closing
 * gesture so the marketing close feels like the same product voice.
 * Optional: only rendered on the landing page's closing block. */
.cta-block__signoff {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-base);
  color: var(--text-muted);
  margin-block-start: var(--space-6);
}

/* Tight top padding on the closing-letter section — the brief feed
 * above already provides visual closure, so the default var(--space-9)
 * lead-in leaves an awkward gap. */
.marketing-section--cta {
  padding-block-start: var(--space-7);
}

.testimonials {
  display: grid;
  gap: var(--space-5);
}

@media (min-width: 768px) {
  .testimonials {
    grid-template-columns: repeat(3, 1fr);
  }
}

.testimonial {
  padding: var(--space-5);
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}

.testimonial__quote {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--text-body);
  margin-block-end: var(--space-4);
}

.testimonial__attribution {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}

.marketing-footer {
  padding: var(--space-7) var(--space-5);
  border-block-start: 1px solid var(--border-subtle);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
  display: flex;
  justify-content: center;
  gap: var(--space-5);
}

.marketing-footer a:hover {
  color: var(--text-body);
}

/* Site colophon — the masthead footer rendered by _site_footer.html on every
 * non-tunnel surface. Replaces the flat .marketing-footer link row: an
 * editorial end-of-page block (wordmark, grouped links) set off from page
 * content by a full-width top hairline with generous spacing above and below.
 * Its tall, wordmark-led body keeps it distinct from the thin fixed
 * .bottom-tab-bar that sits above it on mobile. Base styles are the mobile /
 * stacked layout; the asymmetric desktop layout is the @media block below. */
.site-colophon {
  margin-block-start: var(--space-8);
  padding: var(--space-7) var(--space-5) var(--space-6);
  border-block-start: 1px solid var(--border-subtle);
  font-family: var(--font-body-sans);
  background: var(--bg-page);
}

.site-colophon__wordmark {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-2xl);
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-variation-settings: 'opsz' 32, 'WONK' 1;
  color: var(--text-body);
}

.site-colophon__tagline {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-md);
  color: var(--text-muted);
  margin-block-start: var(--space-2);
}

.site-colophon__groups {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-5);
  margin-block-start: var(--space-6);
}

/* Eyebrow group label — mirrors the eyebrow recipe (small caps, letterspaced). */
.site-colophon__eyebrow {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
}

.site-colophon__links {
  list-style: none;
  margin: var(--space-3) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.site-colophon__links a {
  font-size: var(--text-sm);
  color: var(--text-muted);
  text-decoration: none;
  transition: color var(--duration-quick) var(--easing-default);
}

.site-colophon__links a:hover {
  color: var(--text-body);
}

.site-colophon__foot {
  margin-block-start: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.site-colophon__contact {
  font-size: var(--text-sm);
  color: var(--text-muted);
  text-decoration: none;
  transition: color var(--duration-quick) var(--easing-default);
}

.site-colophon__contact:hover {
  color: var(--text-body);
}

.site-colophon__copy {
  font-size: var(--text-xs);
  color: var(--text-faint);
}

/* Registered-entity trading disclosure (Companies Act 2006). A quiet,
 * full-width line beneath the colophon foot. */
.site-colophon__legal {
  margin-block-start: var(--space-4);
  font-size: var(--text-xs);
  color: var(--text-faint);
}

@media (min-width: 768px) {
  .site-colophon {
    padding: var(--space-8) var(--space-7);
    display: grid;
    grid-template-columns: 1fr auto;
    column-gap: var(--space-9);
    align-items: start;
  }
  .site-colophon__brand { grid-column: 1; }
  .site-colophon__groups {
    grid-column: 2;
    margin-block-start: 0;
    grid-template-columns: repeat(2, auto);
    gap: var(--space-8);
  }
  .site-colophon__foot {
    grid-column: 1 / -1;
    margin-block-start: var(--space-7);
    flex-direction: row;
    justify-content: space-between;
    align-items: baseline;
  }
  .site-colophon__legal {
    grid-column: 1 / -1;
    margin-block-start: var(--space-5);
  }
}

/* Marketing section eyebrow — small caps label that sits above each
 * section title. Frames the section as part of a numbered structure
 * rather than a free-floating block. */
.marketing-section__eyebrow {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-block-end: var(--space-3);
}

/* Standfirst — italic serif sentence that sits between a section
 * title and its body. Pull the title closer when one follows. */
.marketing-section__title:has(+ .marketing-section__standfirst) {
  margin-block-end: var(--space-3);
}

.marketing-section__standfirst {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
  max-inline-size: 55ch;
  margin-block-end: var(--space-6);
}

/* Wider marketing section — used by /pricing where three cards need
 * more inline space than the reading-width default. */
.marketing-section--wide {
  max-inline-size: var(--container-wide);
}

/* "How it works" — editorial process layout. Each row pairs a large
 * Roman numeral and an editorial title/body with a small visual demo
 * of the corresponding product surface. */
.process {
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
  margin-block-start: var(--space-6);
  padding-block-start: var(--space-6);
  border-block-start: 1px solid var(--border-subtle);
}

.process-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-5);
  align-items: start;
}

.process-row + .process-row {
  padding-block-start: var(--space-8);
  border-block-start: 1px solid var(--border-subtle);
}

@media (min-width: 768px) {
  .process-row {
    grid-template-columns: minmax(72px, auto) minmax(0, 1.4fr) minmax(0, 1fr);
    gap: var(--space-6);
    align-items: center;
  }
}

.process-row__numeral {
  font-family: var(--font-display);
  font-size: var(--text-5xl);
  font-style: italic;
  font-weight: 400;
  color: var(--text-faint);
  line-height: 1;
  font-variation-settings: 'opsz' 144;
}

@media (min-width: 768px) {
  .process-row__numeral {
    font-size: var(--text-6xl);
  }
}

.process-row__title {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-snug);
  margin-block-end: var(--space-3);
  font-variation-settings: 'opsz' 36;
}

.process-row__body {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
  max-inline-size: 50ch;
}

.process-row__demo {
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
}

@media (min-width: 768px) {
  .process-row__demo {
    justify-content: flex-end;
  }
}

.process-row__demo-stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  inline-size: 100%;
  max-inline-size: 280px;
}

/* Topic chip — single-line pill, cadence-tinted border, used in the
 * /how-it-works demo. Editorial cousin of the brief-card eyebrow. */
.topic-chip {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-body);
  inline-size: fit-content;
}

.topic-chip em {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-weight: 400;
  font-size: var(--text-xs);
  color: var(--text-muted);
  text-transform: lowercase;
}

.topic-chip[data-cadence='daily'] {
  border-color: color-mix(in oklab, var(--accent-daily) 70%, var(--border-subtle));
}

.topic-chip[data-cadence='weekly'] {
  border-color: color-mix(in oklab, var(--accent-weekly) 70%, var(--border-subtle));
}

.topic-chip[data-cadence='monthly'] {
  border-color: color-mix(in oklab, var(--accent-monthly) 70%, var(--border-subtle));
}

/* Demo brief card — compact variant for the III. process row. */
.brief-card--demo {
  cursor: default;
  inline-size: 100%;
}

.brief-card--demo:hover {
  transform: none;
  box-shadow: var(--shadow-card);
}

/* Demo section-opener — keeps the partial hairline but pulls the
 * margins in so it sits comfortably inside the demo column. */
.section-opener--demo {
  margin-block: 0;
}

.section-opener--demo .section-opener__line {
  flex-basis: 24px;
  flex-grow: 0;
}

/* Page-level marketing hero — used on /pricing. Smaller padding and
 * a tighter headline than the landing hero. */
.marketing-hero--page {
  padding: var(--space-8) var(--space-5) var(--space-6);
}

.marketing-hero--page::before {
  background:
    radial-gradient(ellipse at 80% 0%, var(--accent-weekly-bg) 0%, transparent 50%);
}

.marketing-hero__headline--page {
  font-size: var(--text-4xl);
  margin-inline-start: 0;
}

@media (min-width: 768px) {
  .marketing-hero__headline--page {
    font-size: var(--text-5xl);
  }
}

/* ==========================================================================
   Pricing
   ========================================================================== */

.pricing-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-5);
  margin-block-start: var(--space-6);
  align-items: stretch;
}

@media (min-width: 900px) {
  .pricing-grid {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-4);
  }
}

.pricing-card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: var(--space-6) var(--space-5);
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  isolation: isolate;
  overflow: hidden;
}

/* Cadence-tinted glow in the top corner — same atmosphere as the
 * cover/step-block patterns, kept very soft on the non-featured cards. */
.pricing-card::before {
  content: '';
  position: absolute;
  inset-block-start: -30%;
  inset-inline-end: -20%;
  inline-size: 60%;
  aspect-ratio: 1;
  background: radial-gradient(circle, var(--pricing-tint, var(--accent-weekly-bg)) 0%, transparent 70%);
  border-radius: 50%;
  filter: blur(30px);
  opacity: 0.5;
  z-index: -1;
  pointer-events: none;
}

.pricing-card[data-cadence='daily'] {
  --pricing-tint: var(--accent-daily-bg);
}

.pricing-card[data-cadence='weekly'] {
  --pricing-tint: var(--accent-weekly-bg);
}

.pricing-card[data-cadence='monthly'] {
  --pricing-tint: var(--accent-monthly-bg);
}

/* Featured card — middle plan. Bigger atmosphere, slight elevation
 * on desktop so it visibly anchors the trio. */
.pricing-card--featured::before {
  opacity: 1;
  inline-size: 90%;
  inset-block-start: -40%;
}

.pricing-card--featured {
  box-shadow: var(--shadow-card-hover);
  border-color: transparent;
}

/* Featured lift only when the card sits in a real horizontal row. In the
 * 3-up grid that's >=900px; the four-up grid handles its own lift at >=1100px
 * (below that it's a 2x2 where a lifted middle card would look stranded). */
@media (min-width: 900px) {
  .pricing-grid:not(.pricing-grid--four) .pricing-card--featured {
    transform: translateY(-12px);
  }
}

.pricing-card__tag {
  position: absolute;
  inset-block-start: var(--space-4);
  inset-inline-end: var(--space-4);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-body);
  padding: 2px var(--space-3);
  background: color-mix(in oklab, var(--bg-card) 80%, transparent);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
}

.pricing-card__head {
  margin-block-end: var(--space-4);
}

.pricing-card__plan {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  font-variation-settings: 'opsz' 96;
  margin-block-end: var(--space-3);
}

.pricing-card__positioning {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-base);
  color: var(--text-muted);
  line-height: var(--leading-snug);
  max-inline-size: 32ch;
}

.pricing-card__price {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding-block: var(--space-5);
  margin-block-end: var(--space-5);
  border-block-start: 1px solid var(--border-subtle);
  border-block-end: 1px solid var(--border-subtle);
}

.pricing-card__price-amount {
  font-family: var(--font-display);
  font-size: var(--text-5xl);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  line-height: 1;
  font-variation-settings: 'opsz' 144;
}

.pricing-card__price-period {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.pricing-card__features {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-block-end: var(--space-6);
  flex: 1;
}

.pricing-card__feature {
  font-family: var(--font-body-serif);
  font-size: var(--text-base);
  color: var(--text-body);
  line-height: var(--leading-snug);
  display: flex;
  gap: var(--space-3);
  align-items: baseline;
}

.pricing-card__feature::before {
  content: '·';
  color: var(--text-faint);
  font-size: var(--text-xl);
  line-height: 1;
  flex-shrink: 0;
}

.pricing-card__cta {
  align-self: stretch;
  justify-content: center;
}

.pricing-fine-print {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-base);
  color: var(--text-muted);
  text-align: center;
  margin-block-start: var(--space-7);
  max-inline-size: 60ch;
  margin-inline: auto;
  line-height: var(--leading-relaxed);
}

/* --- Stage (page wrapper; --wide widens for the four-up layout) --------- */
.pricing-stage {
  max-inline-size: var(--container-wide);
  margin-inline: auto;
  padding-block: var(--space-7) var(--space-8);
  padding-inline: var(--space-5);
}

/* The 960px container-wide squeezes four columns — widen the stage for the
 * four-up layout so each card keeps room to breathe. */
.pricing-stage--wide {
  max-inline-size: 1200px;
}

/* --- Flagship card + tag (Power as a peer in the row) ------------------- */
/* Quieter premium treatment: no cadence colour, deeper border. The tag does
 * the signalling so it reads premium without competing with the featured card. */
.pricing-card--flagship {
  --pricing-tint: transparent;
  border-color: var(--text-body);
}

.pricing-card--flagship .pricing-card__plan {
  color: var(--text-body);
}

.pricing-card--flagship::before {
  opacity: 0.15;
  background: radial-gradient(circle, var(--text-body) 0%, transparent 70%);
}

.pricing-card__tag--flagship {
  background: transparent;
  color: var(--text-faint);
  border-color: var(--text-faint);
}

/* --- Price note (annual-billing / savings line) ------------------------- */
.pricing-card__price-note {
  flex-basis: 100%;
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  color: var(--text-faint);
  letter-spacing: var(--tracking-normal);
  margin-block-start: var(--space-2);
}

.pricing-card__price-note--save {
  color: var(--color-success);
}

/* --- Promo activation card ---------------------------------------------- */
/* The /activate confirmation renders the promo's BASE plan in the pricing-card
   idiom, then marks only what the promo changes: the original price struck
   through with the promo price highlighted, a trial badge, and any overridden
   feature line flagged. Calm-not-alarm — the highlight is the savings green
   (never an alert red), matching .pricing-card__price-note--save. Kept in sync
   with stylebook/css/components.css + stylebook/pages/activate-promo.html. */
.pricing-card--promo {
  --pricing-tint: var(--accent-daily-bg);
}

/* Standing alone in the centered auth column, it takes the auth card's width. */
.auth-page > .pricing-card--promo {
  inline-size: 100%;
  max-inline-size: var(--container-narrow);
}

/* The promo's own name, above the base plan's name. */
.pricing-card__offer-eyebrow {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-success);
  margin-block-end: var(--space-2);
}

/* was → now. The base price is struck and quiet; the promo price keeps the
   display weight and carries the savings green. Both live in the price band. */
.pricing-card__price-was {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  color: var(--text-faint);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  line-height: 1;
}

/* Shared "→" between a struck base value and the promo value (price + trial). */
.pricing-card__delta-arrow {
  font-family: var(--font-body-sans);
  font-size: var(--text-xl);
  color: var(--text-muted);
  line-height: 1;
}

.pricing-card__price-now {
  font-family: var(--font-display);
  font-size: var(--text-5xl);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  line-height: 1;
  font-variation-settings: 'opsz' 144;
  color: var(--color-success);
}

/* Trial — shown was→now like the price, on its own line in the price band: the
   base's trial (or "No free trial") struck, then the promo's trial as a quiet
   success-tinted pill. A no-base fallback shows just the pill. */
.pricing-card__trial {
  flex-basis: 100%;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-block-start: var(--space-3);
}

.pricing-card__trial-was {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-faint);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}

.pricing-card__trial-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-success);
  background: color-mix(in oklab, var(--color-success) 14%, transparent);
  padding: 4px var(--space-3);
  border-radius: var(--radius-pill);
}

/* Feature diff vs the base. 'same' lines use the plain .pricing-card__feature;
   changed/added carry the savings green with a + marker; removed is struck. */
.pricing-card__feature--added,
.pricing-card__feature--changed {
  color: var(--color-success);
}

.pricing-card__feature--added::before,
.pricing-card__feature--changed::before {
  content: '+';
  color: var(--color-success);
  font-weight: 600;
}

.pricing-card__feature--removed {
  color: var(--text-faint);
  text-decoration: line-through;
}

/* Promotional terms — small, quiet, in a hairline box inside the card. */
.pricing-card__terms {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
  line-height: var(--leading-snug);
  background: color-mix(in oklab, var(--bg-card) 70%, var(--border-subtle));
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  padding: var(--space-3);
  margin-block-end: var(--space-4);
}

/* Agree + Sign up live in the card footer; the CTA stretches full width. */
.pricing-card__form {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.pricing-card__form .button {
  inline-size: 100%;
  justify-content: center;
}

/* --- Trust strip -------------------------------------------------------- */
.pricing-trust {
  display: flex;
  justify-content: center;
  gap: var(--space-4);
  margin-block-start: var(--space-5);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
}

.pricing-trust__item::before {
  content: '·';
  margin-inline-end: var(--space-2);
  color: var(--text-faint);
}

.pricing-trust__item:first-child::before {
  content: none;
}

/* Narrow phones: the inline ·-separated row gets cramped and wraps
   awkwardly, so stack the trust items vertically, centered, and drop
   the dot separators (they only read as separators in a row). */
@media (max-width: 480px) {
  .pricing-trust {
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
  }

  .pricing-trust__item::before {
    content: none;
    margin-inline-end: 0;
  }
}

/* --- Billing toggle (monthly <-> yearly) -------------------------------- */
.billing-toggle-row {
  display: flex;
  justify-content: center;
  margin-block-start: var(--space-5);
}

.billing-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1);
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  margin-block: var(--space-6) 0;
}

.billing-toggle__option {
  appearance: none;
  background: transparent;
  border: 0;
  border-radius: var(--radius-pill);
  padding: var(--space-2) var(--space-5);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  font-weight: 500;
  letter-spacing: var(--tracking-normal);
  color: var(--text-muted);
  cursor: pointer;
  transition:
    background var(--duration-quick) var(--easing-default),
    color var(--duration-quick) var(--easing-default);
}

.billing-toggle__option:hover {
  color: var(--text-body);
}

.billing-toggle__option[aria-pressed='true'] {
  background: var(--bg-page);
  color: var(--text-body);
  box-shadow: inset 0 0 0 1px var(--border-subtle);
}

.billing-toggle__badge {
  display: inline-block;
  margin-inline-start: var(--space-2);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-success);
}

/* --- Variant: four even columns (unsquished) ---------------------------- */
.pricing-grid--four {
  margin-block-start: var(--space-7);
}

@media (min-width: 720px) {
  .pricing-grid--four {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-4);
  }
}

@media (min-width: 1100px) {
  .pricing-grid--four {
    grid-template-columns: repeat(4, 1fr);
    gap: var(--space-4);
  }

  .pricing-grid--four .pricing-card--featured {
    transform: translateY(-10px);
  }
}

/* Four columns are tighter than three — shrink the price number and pull the
 * feature rhythm in so each card breathes instead of squishing. */
.pricing-grid--four .pricing-card { padding: var(--space-5) var(--space-4); }
.pricing-grid--four .pricing-card__price-amount { font-size: var(--text-4xl); }
.pricing-grid--four .pricing-card__features { gap: var(--space-2); }
.pricing-grid--four .pricing-card__feature { font-size: var(--text-sm); }

/* ==========================================================================
   Chat — full-viewport, two-zone (sidebar + reading column)
   ========================================================================== */

/* Outer page: fills the viewport beneath the app header (and above the
   mobile bottom tab bar). The document does NOT scroll — only .chat-log
   does — which keeps the header pinned and the input always reachable.

   Sizing strategy: body becomes a flex column at the chat surface; the
   header is auto-height, chat-page takes the rest. No magic constants. */
body:has(.chat-page) {
  /* The full-viewport chat shell must equal the *visible* area. 100dvh
     tracks the dynamic viewport (URL bar shown/hidden), but the reset
     gives every body `min-block-size: 100vh` — and 100vh is the LARGE
     viewport, which never shrinks for the URL bar. That floor would
     force the shell taller than the visible area and push the composer
     below the fold (clipped, unscrollable under overflow:hidden). So we
     drop the floor here and let 100dvh own the height. The keyboard is
     handled by the browser: Android resizes the layout via the viewport
     meta (interactive-widget=resizes-content); iOS pans to lift the
     input above the keyboard. */
  block-size: 100dvh;
  min-block-size: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* On iOS the soft keyboard makes Safari pan the page to reveal the
   focused input, dragging the position:fixed bottom tab bar up with it
   and leaving a gap above the keyboard. chat.js sets body.is-keyboard-open
   while the keyboard is up; hide the bar (you don't need bottom nav
   mid-message) and reclaim its reserved padding so the composer sits
   flush above the keyboard. The class+:has() selector out-specifies the
   plain :has(.bottom-tab-bar) padding rule below, so no !important. */
body.is-keyboard-open .bottom-tab-bar {
  display: none;
}

body.is-keyboard-open:has(.bottom-tab-bar) {
  padding-block-end: 0;
}

/* Chat-only, mobile: tighten the gap below the composer. The global
   bottom-tab-bar reservation is 64px (kept on scrolling pages so their
   content clears the fixed bar); the chat composer is its own flush
   bottom element, so a smaller 37px reserve seats the input just above
   the tab bar. Later than the global rule + equal specificity, so it
   wins; the is-keyboard-open rule above (higher specificity) still
   zeroes it when the keyboard is open. */
@media (max-width: 767px) {
  body:has(.chat-page) {
    padding-block-end: 37px;
  }
}

/* The chat-page lives inside <main> in the app shell. <main>'s default
   display:block doesn't propagate the flex sizing chain, so the inner
   chat-log can't be height-constrained and never scrolls. Make <main>
   a flex column so chat-page's flex:1 / min-block-size:0 actually
   fills the remaining viewport. */
body:has(.chat-page) > main {
  flex: 1;
  min-block-size: 0;
  display: flex;
  flex-direction: column;
}

.chat-page {
  flex: 1;
  min-block-size: 0;
  display: grid;
  /* minmax(0, 1fr) is critical — without the explicit 0 minimum, the
     1fr column defaults to min-content, so a long unbreakable word in
     a message (or a long placeholder) expands the column past the
     viewport and the whole pane clips on the right. */
  grid-template-columns: minmax(0, 1fr);
  inline-size: 100%;
  background: var(--bg-page);
  position: relative;
  overflow: hidden;
}

@media (min-width: 768px) {
  .chat-page {
    grid-template-columns: 300px minmax(0, 1fr);
  }
}

/* ── Sidebar ──────────────────────────────────────────────────────────── */

.chat-sidebar {
  display: flex;
  flex-direction: column;
  min-block-size: 0;
  min-inline-size: 0;
  border-inline-end: 1px solid var(--border-subtle);
  /* Calm rail: a slight warm-card tint over the page substrate so the
     sidebar reads as a distinct surface without competing with the
     pane. The chat-page is full-bleed so this surface runs all the way
     to the viewport edge — no abrupt cut. */
  background: color-mix(in oklab, var(--bg-card) 30%, var(--bg-page) 70%);
  position: relative;
}

.chat-sidebar::before {
  /* Soft ambient warmth in the upper-right corner, fades smoothly into
     the rail. No hard edges anywhere. */
  content: '';
  position: absolute;
  inset-block-start: -10%;
  inset-inline-start: -10%;
  inline-size: 120%;
  block-size: 50%;
  background: radial-gradient(
    ellipse at 50% 0%,
    color-mix(in oklab, var(--accent-weekly-bg) 70%, transparent) 0%,
    transparent 70%
  );
  filter: blur(20px);
  opacity: 0.7;
  pointer-events: none;
  z-index: 0;
}

.chat-sidebar > * {
  position: relative;
  z-index: 1;
}

@media (max-width: 767px) {
  /* Mobile: sidebar lives inside the drawer overlay (anchored to the
     chat-page since it's position:relative and clips overflow). */
  .chat-sidebar {
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    inline-size: min(320px, 86vw);
    z-index: 30;
    border-inline-end: 1px solid var(--border-subtle);
    box-shadow: var(--shadow-modal);
    transform: translateX(-100%);
    transition: transform var(--duration-standard) var(--easing-default);
  }
  .chat-page.is-drawer-open .chat-sidebar {
    transform: translateX(0);
  }
}

.chat-sidebar__header {
  padding: var(--space-5) var(--space-5) var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.chat-sidebar__title {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0;
}

/* "+ New conversation" — soft tactile button, reads as a button without
   shouting. Borders + subtle gradient lift it off the page. */
.chat-new-button {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-body);
  box-shadow: var(--shadow-card);
  cursor: pointer;
  transition:
    transform var(--duration-quick) var(--easing-default),
    box-shadow var(--duration-quick) var(--easing-default),
    border-color var(--duration-quick) var(--easing-default);
}

.chat-new-button:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-card-hover);
  border-color: var(--text-muted);
}

.chat-new-button__plus {
  inline-size: 18px;
  block-size: 18px;
  border-radius: 50%;
  background: var(--text-body);
  color: var(--bg-page);
  display: grid;
  place-items: center;
  font-weight: 600;
  font-size: 13px;
  line-height: 1;
}

.chat-sidebar__list {
  flex: 1;
  list-style: none;
  margin: 0;
  padding: var(--space-2) var(--space-3) var(--space-5);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.chat-sidebar__group-label {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
  padding: var(--space-4) var(--space-3) var(--space-2);
}

/* Conversation row — a soft tactile pill that highlights when active */
.chat-conv {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  text-decoration: none;
  color: inherit;
  transition: background var(--duration-quick) var(--easing-default);
}

.chat-conv:hover {
  background: color-mix(in oklab, var(--bg-card) 70%, transparent);
}

.chat-conv.is-active {
  background: var(--bg-card);
  box-shadow: var(--shadow-card);
}

.chat-conv__row {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}

.chat-conv__title {
  flex: 1;
  font-family: var(--font-body-sans);
  font-size: var(--text-base);
  font-weight: 500;
  color: var(--text-body);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.35;
}

.chat-conv__time {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  color: var(--text-faint);
  flex-shrink: 0;
}

.chat-conv__preview {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
  line-height: var(--leading-normal);
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.chat-conv__chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  margin-block-start: var(--space-1);
  padding: 1px var(--space-2);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  border-radius: var(--radius-pill);
  color: var(--text-muted);
  background: color-mix(in oklab, var(--text-body) 6%, transparent);
  align-self: flex-start;
}

.chat-conv__chip[data-cadence='daily'] {
  background: var(--accent-daily-bg);
  color: color-mix(in oklab, var(--text-body) 80%, var(--accent-daily) 20%);
}
.chat-conv__chip[data-cadence='weekly'] {
  background: var(--accent-weekly-bg);
  color: color-mix(in oklab, var(--text-body) 80%, var(--accent-weekly) 20%);
}
.chat-conv__chip[data-cadence='monthly'] {
  background: var(--accent-monthly-bg);
  color: color-mix(in oklab, var(--text-body) 80%, var(--accent-monthly) 20%);
}
.chat-conv__chip--editor {
  background: color-mix(in oklab, var(--accent-monthly) 18%, transparent);
  color: color-mix(in oklab, var(--text-body) 80%, var(--accent-monthly) 20%);
}

.chat-conv__unread {
  inline-size: 8px;
  block-size: 8px;
  border-radius: 50%;
  background: var(--text-body);
  flex-shrink: 0;
  align-self: center;
}

.chat-conv__more {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-end: var(--space-2);
  transform: translateY(-50%);
  inline-size: 28px;
  block-size: 28px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-sm);
  color: var(--text-faint);
  background: transparent;
  opacity: 0;
  transition: opacity var(--duration-quick) var(--easing-default), background var(--duration-quick) var(--easing-default);
  cursor: pointer;
}

.chat-conv:hover .chat-conv__more,
.chat-conv:focus-within .chat-conv__more,
.chat-conv.is-active .chat-conv__more {
  opacity: 1;
}

.chat-conv__more:hover {
  background: color-mix(in oklab, var(--text-body) 8%, transparent);
  color: var(--text-body);
}

.chat-conv__more svg {
  inline-size: 16px;
  block-size: 16px;
  stroke: currentColor;
  fill: currentColor;
}

.chat-sidebar__empty {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-sm);
  color: var(--text-muted);
  padding: var(--space-5) var(--space-4);
  text-align: center;
}

/* Drawer scrim (mobile only) */
.chat-drawer-scrim {
  display: none;
}

@media (max-width: 767px) {
  .chat-page.is-drawer-open .chat-drawer-scrim {
    display: block;
    position: absolute;
    inset: 0;
    background: color-mix(in oklab, var(--text-body) 30%, transparent);
    backdrop-filter: blur(2px);
    z-index: 25;
  }
}

/* ── Pane (right side: header + log + input) ──────────────────────────── */

.chat-pane {
  display: flex;
  flex-direction: column;
  min-block-size: 0;
  min-inline-size: 0;
  background: var(--bg-page);
}

.chat-pane__header {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-block-end: 1px solid var(--border-subtle);
  background: color-mix(in oklab, var(--bg-page) 92%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

@media (max-width: 767px) {
  .chat-pane__header {
    padding: var(--space-3) var(--space-3);
    gap: var(--space-2);
  }
}

.chat-pane__hamburger {
  display: none;
  inline-size: 36px;
  block-size: 36px;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-body);
  border: 1px solid transparent;
  cursor: pointer;
  place-items: center;
}

.chat-pane__hamburger svg {
  inline-size: 20px;
  block-size: 20px;
}

.chat-pane__hamburger:hover {
  background: color-mix(in oklab, var(--text-body) 6%, transparent);
}

@media (max-width: 767px) {
  .chat-pane__hamburger { display: grid; }
}

.chat-pane__titles {
  flex: 1;
  min-inline-size: 0;
}

.chat-pane__title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
  color: var(--text-body);
  margin: 0;
  font-variation-settings: 'opsz' 24;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

@media (min-width: 768px) {
  .chat-pane__title {
    font-size: var(--text-xl);
    font-variation-settings: 'opsz' 30;
  }
}

.chat-pane__subtitle {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin-block-start: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chat-pane__subtitle a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-color: var(--text-faint);
}

.chat-pane__subtitle a:hover {
  color: var(--text-body);
  text-decoration-color: var(--text-body);
}

/* Per-conversation model picker on the chat header */
.chat-model-picker {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
}

.chat-model-picker__label {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
}

.chat-model-picker__select {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-body);
  background: transparent;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  padding: 4px var(--space-2);
  cursor: pointer;
  transition: border-color var(--duration-quick) var(--easing-default);
}

.chat-model-picker__select:hover {
  border-color: color-mix(in oklab, var(--text-body) 24%, transparent);
}

@media (max-width: 767px) {
  .chat-model-picker__label { display: none; }
}

/* Action menu (kebab) on the chat header */
.chat-pane__menu {
  position: relative;
}

.chat-pane__menu-button {
  inline-size: 36px;
  block-size: 36px;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-muted);
  border: 1px solid transparent;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background var(--duration-quick) var(--easing-default), color var(--duration-quick) var(--easing-default);
}

.chat-pane__menu-button:hover {
  background: color-mix(in oklab, var(--text-body) 6%, transparent);
  color: var(--text-body);
}

.chat-pane__menu-button svg {
  inline-size: 18px;
  block-size: 18px;
}

.chat-pane__menu-sheet {
  position: absolute;
  inset-block-start: calc(100% + 6px);
  inset-inline-end: 0;
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-modal);
  min-inline-size: 200px;
  padding: var(--space-2);
  z-index: 20;
  display: flex;
  flex-direction: column;
}

.chat-pane__menu-link {
  display: block;
  text-align: start;
  padding: var(--space-3);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-body);
  border-radius: var(--radius-sm);
  background: transparent;
  border: 0;
  cursor: pointer;
  transition: background var(--duration-quick) var(--easing-default);
  width: 100%;
}

.chat-pane__menu-link:hover {
  background: color-mix(in oklab, var(--text-body) 6%, transparent);
}

.chat-pane__menu-link--destructive {
  color: var(--color-error);
}

/* ── Log ──────────────────────────────────────────────────────────────── */

.chat-log {
  flex: 1;
  min-block-size: 0;
  overflow-y: auto;
  padding-block: var(--space-6) var(--space-7);
  scroll-behavior: smooth;
}

.chat-log__inner {
  max-inline-size: var(--container-reading);
  margin-inline: auto;
  padding-inline: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

/* User message — bubble (right-aligned), tactile and warm */
.chat-message--user {
  align-self: flex-end;
  max-inline-size: 80%;
  padding: var(--space-4) var(--space-5);
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  border-end-end-radius: var(--radius-sm);
  font-family: var(--font-body-sans);
  font-size: var(--text-base);
  line-height: var(--leading-relaxed);
  color: var(--text-body);
  box-shadow: var(--shadow-card);
  /* Break long URLs / unbreakable words so they can't expand the
     column past the viewport on mobile. */
  overflow-wrap: anywhere;
  word-break: break-word;
}

.chat-message--user .chat-message__time {
  display: block;
  margin-block-start: var(--space-2);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  color: var(--text-faint);
  text-align: end;
}

/* User message — pending/optimistic state */
.chat-message--user.is-pending {
  opacity: 0.55;
}

/* Editor reply — editorial, no bubble. Reads like a short brief. */
.chat-message--editor {
  align-self: stretch;
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--text-body);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  overflow-wrap: anywhere;
  word-break: break-word;
}

.chat-message__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.chat-message--editor p {
  margin: 0;
}

.chat-message--editor strong { font-weight: 600; }
.chat-message--editor em { font-style: italic; }

.chat-message--editor a {
  color: var(--text-body);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-color: var(--text-faint);
}

.chat-message--editor a:hover {
  text-decoration-color: var(--text-body);
}

/* Lists — tighter than reading-prose lists; markers in muted faint */
.chat-message--editor ul,
.chat-message--editor ol {
  margin: 0;
  padding-inline-start: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.chat-message--editor ul li::marker { color: var(--text-faint); }
.chat-message--editor ol li::marker { color: var(--text-faint); font-variant-numeric: tabular-nums; }

/* Inline code + fenced blocks */
.chat-message--editor code {
  font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  font-size: 0.92em;
  background: color-mix(in oklab, var(--text-body) 6%, transparent);
  border-radius: var(--radius-sm);
  padding: 1px 6px;
}

.chat-message--editor pre {
  margin: 0;
  padding: var(--space-4) var(--space-5);
  background: color-mix(in oklab, var(--text-body) 5%, transparent);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  overflow-x: auto;
  font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
}

.chat-message--editor pre code {
  background: transparent;
  padding: 0;
  border-radius: 0;
  font-size: inherit;
}

/* Blockquote — quiet left rule, no theatre */
.chat-message--editor blockquote {
  margin: 0;
  padding-inline-start: var(--space-4);
  border-inline-start: 2px solid var(--border-subtle);
  color: var(--text-muted);
  font-style: italic;
}

/* Headings within editor replies — discourage huge ones via styling */
.chat-message--editor h1,
.chat-message--editor h2,
.chat-message--editor h3,
.chat-message--editor h4,
.chat-message--editor h5,
.chat-message--editor h6 {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  line-height: var(--leading-snug);
  margin: 0;
  font-variation-settings: 'opsz' 24;
  letter-spacing: var(--tracking-tight);
}

/* Tables (markdown produces them via plugin extensions; default
   commonmark doesn't, but cheap to support if added later) */
.chat-message--editor table {
  border-collapse: collapse;
  font-size: var(--text-sm);
  margin: 0;
}

.chat-message--editor th,
.chat-message--editor td {
  padding: var(--space-2) var(--space-3);
  border-block-end: 1px solid var(--border-subtle);
  text-align: start;
}

/* Sign-off line for editor messages */
.chat-message__sign {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
  margin-block-start: var(--space-2);
}

.chat-message__sign::before {
  content: '—';
  color: var(--text-faint);
}

/* Inline tool confirmation inside an editor message
   (e.g. "I created a topic 'Quantum computing'") */
.chat-message__confirmation {
  padding: var(--space-3) var(--space-4);
  background: color-mix(in oklab, var(--accent-weekly-bg) 60%, transparent);
  border-inline-start: 2px solid var(--accent-weekly);
  border-radius: var(--radius-sm);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-body);
  font-style: normal;
}

/* ── Propose-and-confirm card (guardrails T4/T5) ───────────────────
   Shown inside an editor chat message when the agent stages a
   high-impact change — create / change / pause a topic, update the
   profile. The change waits on the user's Confirm click, closing the
   confused-deputy risk. See docs/company/projects/guardrails.md. */
.chat-proposal {
  margin-top: var(--space-3);
  padding: var(--space-3) var(--space-4) var(--space-4);
  background: var(--bg-card-elevated);
  border: 1px solid var(--border-subtle);
  border-inline-start: 3px solid var(--color-warning);
  border-radius: var(--radius-sm);
  font-family: var(--font-body-sans);
}
.chat-proposal__head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}
.chat-proposal__icon {
  width: 15px;
  height: 15px;
  flex: none;
  color: var(--color-warning);
}
.chat-proposal__eyebrow {
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  font-weight: 600;
}
.chat-proposal__summary {
  margin: 0;
  font-size: var(--text-base);
  line-height: var(--leading-snug);
  color: var(--text-body);
}
.chat-proposal__detail {
  list-style: none;
  margin: var(--space-2) 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
}
.chat-proposal__detail li {
  font-size: var(--text-sm);
  color: var(--text-muted);
}
.chat-proposal__actions {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-4);
}
.chat-proposal__btn {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  font-weight: 600;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background var(--duration-quick) var(--easing-default),
              border-color var(--duration-quick) var(--easing-default);
}
.chat-proposal__btn--confirm {
  background: var(--text-body);
  color: var(--bg-card);
}
.chat-proposal__btn--confirm:hover {
  background: color-mix(in oklab, var(--text-body) 85%, var(--color-warning));
}
.chat-proposal__btn--dismiss {
  background: transparent;
  color: var(--text-muted);
  border-color: var(--border-subtle);
}
.chat-proposal__btn--dismiss:hover {
  background: var(--bg-page);
}
.chat-proposal__settled {
  display: none;
  margin-top: var(--space-3);
  font-size: var(--text-sm);
  align-items: baseline;
  gap: var(--space-2);
}
.chat-proposal__settled-mark {
  font-weight: 700;
}
.chat-proposal[data-state="confirmed"] .chat-proposal__actions,
.chat-proposal[data-state="dismissed"] .chat-proposal__actions {
  display: none;
}
.chat-proposal[data-state="confirmed"] .chat-proposal__settled,
.chat-proposal[data-state="dismissed"] .chat-proposal__settled {
  display: flex;
}
.chat-proposal[data-state="confirmed"] {
  border-inline-start-color: var(--color-success);
  background: color-mix(in oklab, var(--color-success) 7%, var(--bg-card));
}
.chat-proposal[data-state="confirmed"] .chat-proposal__settled {
  color: color-mix(in oklab, var(--color-success) 70%, var(--text-body));
}
.chat-proposal[data-state="dismissed"] {
  border-inline-start-color: var(--border-subtle);
  background: var(--bg-page);
  opacity: 0.85;
}
.chat-proposal[data-state="dismissed"] .chat-proposal__summary {
  color: var(--text-muted);
}
.chat-proposal[data-state="dismissed"] .chat-proposal__settled {
  color: var(--text-muted);
}
.chat-proposal[data-state="dismissed"] .chat-proposal__head {
  display: none;
}

/* Typing / "writing" indicator */
.chat-typing {
  align-self: stretch;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
}

.chat-typing__dots {
  display: inline-flex;
  gap: 4px;
  align-items: center;
}

.chat-typing__dot {
  inline-size: 6px;
  block-size: 6px;
  border-radius: 50%;
  background: var(--text-muted);
  opacity: 0.4;
  animation: chat-typing-bounce 1.2s infinite ease-in-out;
}

.chat-typing__dot:nth-child(2) { animation-delay: 0.15s; }
.chat-typing__dot:nth-child(3) { animation-delay: 0.30s; }

@keyframes chat-typing-bounce {
  0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-3px); }
}

@media (prefers-reduced-motion: reduce) {
  .chat-typing__dot { animation: none; opacity: 0.7; }
}

/* Date divider in the log */
.chat-divider {
  align-self: stretch;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
  margin-block: var(--space-3);
}

.chat-divider::before,
.chat-divider::after {
  content: '';
  flex: 1;
  border-block-start: 1px dashed var(--border-subtle);
}

/* ── Input zone ───────────────────────────────────────────────────────── */

.chat-input-zone {
  flex-shrink: 0;
  padding: var(--space-4) var(--space-5) var(--space-5);
  border-block-start: 1px solid var(--border-subtle);
  background: color-mix(in oklab, var(--bg-page) 92%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

@media (max-width: 767px) {
  .chat-input-zone {
    padding: var(--space-3) var(--space-3) var(--space-4);
  }
}

/* The form is just a flex row holding the input box and the send
   button as siblings. The chrome (border, radius, shadow) lives on
   .chat-input__inner so the send circle sits OUTSIDE the rectangle.
   align-items: flex-end keeps the send anchored to the bottom-right
   when the input grows multi-line. */
.chat-input {
  display: flex;
  gap: var(--space-3);
  align-items: flex-end;
  max-inline-size: var(--container-reading);
  margin-inline: auto;
}

/* The actual input box. Fixed-pixel radius (radius-lg = 20px) means
   the box keeps the same corners regardless of how tall it grows —
   it reads as "a chat composer that's expanding" instead of an
   ever-elongating pill. */
.chat-input__inner {
  flex: 1;
  min-inline-size: 0;
  display: flex;
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  padding: var(--space-3) var(--space-4);
  box-shadow: var(--shadow-card);
  transition:
    border-color var(--duration-quick) var(--easing-default),
    box-shadow var(--duration-quick) var(--easing-default);
}

.chat-input__inner:focus-within {
  border-color: var(--text-muted);
  box-shadow: var(--shadow-card-hover);
}

.chat-input__field {
  flex: 1;
  inline-size: 100%;
  display: block;
  border: 0;
  background: transparent;
  padding: 0;
  font-family: var(--font-body-sans);
  /* Slightly smaller than message body — chat input doesn't need
     reading-pace type. */
  font-size: var(--text-base);
  color: var(--text-body);
  resize: none;
  min-block-size: 22px;
  max-block-size: 200px;
  line-height: 1.5;
  outline: none;
  /* Hide the scrollbar by default — a long placeholder that wraps
     on mobile would otherwise trigger a tiny native scrollbar inside
     the input. JS toggles overflow-y back to auto only when actual
     typed content exceeds max-block-size. */
  overflow-y: hidden;
}

@media (max-width: 767px) {
  /* 16px minimum stops iOS Safari from zooming the page when the field
     is focused (it zooms any input below 16px). Mobile-only so the
     deliberately smaller desktop composer type is preserved. Placed
     after the base rule so it wins on source order (same specificity). */
  .chat-input__field {
    font-size: 16px;
  }
}

.chat-input__field::placeholder {
  color: var(--text-faint);
  font-style: italic;
}

/* Send button — circular, nestled inside the pill. Switches between a
   "ready" state (dark fill, full contrast) and a "resting" state (light
   surface, muted) based on whether the textarea has content, so it
   reads as inactive when there's nothing to send. */
.chat-input__send {
  position: relative;
  flex-shrink: 0;
  inline-size: 40px;
  block-size: 40px;
  border-radius: 50%;
  background: var(--text-body);
  color: var(--bg-page);
  border: 0;
  display: grid;
  place-items: center;
  cursor: pointer;
  overflow: hidden;
  isolation: isolate;
  transition:
    transform var(--duration-quick) var(--easing-default),
    background var(--duration-quick) var(--easing-default),
    color var(--duration-quick) var(--easing-default),
    box-shadow var(--duration-quick) var(--easing-default),
    opacity var(--duration-quick) var(--easing-default);
}

.chat-input__send:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

/* Resting state: textarea is empty (placeholder visible). The button
   recedes to a soft surface so it doesn't shout for attention. The
   :has() climbs out of the inner wrapper to reach the send sibling. */
.chat-input:has(.chat-input__field:placeholder-shown) .chat-input__send {
  background: color-mix(in oklab, var(--text-body) 12%, var(--bg-card) 88%);
  color: var(--text-faint);
  cursor: default;
}

.chat-input:has(.chat-input__field:placeholder-shown) .chat-input__send:hover {
  transform: none;
  box-shadow: none;
}

.chat-input__send:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

.chat-input__send svg {
  position: relative;
  z-index: 1;
  inline-size: 18px;
  block-size: 18px;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Gradient flash on press — immediate tactile feedback */
.chat-input__send::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: conic-gradient(
    from 220deg,
    var(--accent-daily) 0%,
    var(--accent-weekly) 35%,
    var(--accent-monthly) 65%,
    var(--accent-daily) 100%
  );
  opacity: 0;
  pointer-events: none;
  z-index: 0;
  transform: scale(0.4);
}

.chat-input__send:active:not(:disabled) {
  transform: translateY(0) scale(0.96);
}

/* The flash is JS-triggered (chat.js toggles .is-flashing on submit)
   rather than tied to :active — :active only holds while the mouse
   button is down, so a normal sub-100ms click would cut the
   animation off mid-way. Class-based ensures the full 600ms plays
   regardless of how long the user held the button. */
.chat-input__send.is-flashing::before {
  animation: chat-send-flash 600ms ease-out;
}

@keyframes chat-send-flash {
  0% { opacity: 1; transform: scale(0.4); }
  100% { opacity: 0; transform: scale(2); }
}

@media (prefers-reduced-motion: reduce) {
  .chat-input__send::before { animation: none !important; }
  .chat-input__send:active:not(:disabled) { transform: none; }
}

.chat-input__hint {
  max-inline-size: var(--container-reading);
  margin: var(--space-2) auto 0;
  padding-inline: var(--space-3);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  color: var(--text-faint);
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
}

@media (max-width: 767px) {
  /* No helper text on mobile: the keyboard-shortcut hint is irrelevant
     on a soft keyboard, so the row would be empty — hide it. */
  .chat-input__hint { display: none; }
}

/* ── Inline upgrade card ──────────────────────────────────────────────── */
/* Anchored to the assistant message whose editor would have used web
   tools but couldn't on this plan. System voice (not the editor); near-
   footnote visual weight. All colors come from semantic tokens so the
   card adapts to the active theme — no hardcoded brights. Suppressed
   once the user has CHAT_WEB_TOOLS. */

.chat-upgrade-card {
  align-self: stretch;
  margin-block: var(--space-1) var(--space-3);
  display: flex;
  align-items: baseline;
  justify-content: flex-start;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: 0;
  background: transparent;
  border: 0;
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  color: var(--text-faint);
  line-height: 1.5;
}

.chat-upgrade-card__lede {
  flex: 1;
  min-inline-size: 0;
}

.chat-upgrade-card__action {
  color: var(--text-muted);
  text-decoration: none;
  font-weight: 500;
  border-block-end: 1px dotted currentColor;
  white-space: nowrap;
  transition: color 120ms ease;
}

.chat-upgrade-card__action:hover,
.chat-upgrade-card__action:focus-visible {
  color: var(--text-body);
}

/* ── Chat fair-use notice ─────────────────────────────────────────────────
   Calm system note shown in place of an editor reply when a chat turn is
   blocked by the hidden fair-use cap. Same footnote weight as the upgrade
   card — informational, never an alarm. All colors from semantic tokens. */

.chat-fairuse-notice {
  align-self: stretch;
  margin-block: var(--space-1) var(--space-3);
  padding: 0;
  background: transparent;
  border: 0;
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  color: var(--text-faint);
  line-height: 1.5;
}

.chat-fairuse-notice__lede {
  display: block;
  min-inline-size: 0;
}

/* ── Empty state ──────────────────────────────────────────────────────── */

.chat-empty {
  align-self: stretch;
  text-align: center;
  padding: var(--space-9) var(--space-5) var(--space-7);
}

.chat-empty__title {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  color: var(--text-muted);
  margin-block-end: var(--space-3);
  font-variation-settings: 'opsz' 72;
  line-height: var(--leading-snug);
  max-inline-size: 22ch;
  margin-inline: auto;
}

.chat-empty__body {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-md);
  color: var(--text-muted);
  max-inline-size: 36ch;
  margin-inline: auto;
  margin-block-end: var(--space-5);
}

.chat-empty__panel {
  margin: var(--space-6) auto 0;
  inline-size: 100%;
  max-inline-size: 480px;
  block-size: 160px;
  border-radius: var(--radius-xl);
  background:
    radial-gradient(ellipse at 25% 20%, var(--accent-weekly-bg) 0%, transparent 60%),
    radial-gradient(ellipse at 75% 80%, var(--accent-daily-bg) 0%, transparent 60%),
    radial-gradient(ellipse at 50% 50%, var(--accent-monthly-bg) 0%, transparent 70%),
    var(--bg-card);
  filter: blur(1px);
}

.chat-empty__suggestions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
  margin-block-start: var(--space-5);
}

.chat-empty__suggestion {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-body);
  padding: var(--space-2) var(--space-4);
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: border-color var(--duration-quick) var(--easing-default), transform var(--duration-quick) var(--easing-default);
}

.chat-empty__suggestion:hover {
  border-color: var(--text-muted);
  transform: translateY(-1px);
}

/* ── Brief-link strip (top of pane when chat is about a brief) ───────── */

.chat-brief-link {
  flex-shrink: 0;
  padding: var(--space-3) var(--space-5);
  background: color-mix(in oklab, var(--bg-card) 60%, transparent);
  border-block-end: 1px solid var(--border-subtle);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  overflow: hidden;
}

@media (max-width: 767px) {
  .chat-brief-link {
    padding: var(--space-2) var(--space-3);
    gap: var(--space-2);
    font-size: var(--text-xs);
  }
}

.chat-brief-link__label {
  flex-shrink: 0;
}

.chat-brief-link__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--text-body);
  text-decoration: none;
  font-weight: 500;
  flex: 1;
  min-inline-size: 0;
}

.chat-brief-link__link:hover .chat-brief-link__title {
  text-decoration: underline;
  text-underline-offset: 2px;
}

.chat-brief-link__title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-inline-size: 0;
}

.chat-brief-link__arrow {
  inline-size: 14px;
  block-size: 14px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
}

/* ==========================================================================
   Brief CTA — replaces the embedded chat at the bottom of a brief
   ========================================================================== */

/* Designed to recede beneath the findings, not compete with them.
   No card fill, no shadow — just a hairline frame, a barely-there
   ambient gradient corner, and editorial typography. */
.brief-cta {
  position: relative;
  margin-block: var(--space-7) var(--space-9);
  padding: var(--space-6) var(--space-5);
  background: transparent;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  overflow: hidden;
  isolation: isolate;
  text-align: start;
}

.brief-cta::before {
  content: '';
  position: absolute;
  inset-block-start: -60%;
  inset-inline-end: -30%;
  inline-size: 70%;
  aspect-ratio: 1;
  background: radial-gradient(circle, var(--cta-tint, var(--accent-weekly-bg)) 0%, transparent 65%);
  border-radius: 50%;
  filter: blur(60px);
  opacity: 0.45;
  z-index: -1;
  pointer-events: none;
}

.brief-cta[data-cadence='daily'] { --cta-tint: var(--accent-daily-bg); }
.brief-cta[data-cadence='weekly'] { --cta-tint: var(--accent-weekly-bg); }
.brief-cta[data-cadence='monthly'] { --cta-tint: var(--accent-monthly-bg); }

.brief-cta__eyebrow {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-block-end: var(--space-3);
}

.brief-cta__title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-snug);
  margin-block-end: var(--space-3);
  font-variation-settings: 'opsz' 30;
  max-inline-size: 36ch;
  color: var(--text-body);
}

.brief-cta__lede {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-md);
  color: var(--text-muted);
  margin-block-end: var(--space-5);
  max-inline-size: 52ch;
  line-height: var(--leading-relaxed);
}

/* Outlined / secondary — quiet enough not to outshine the findings */
.brief-cta__action {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  background: transparent;
  color: var(--text-body);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  font-family: var(--font-body-sans);
  font-size: var(--text-base);
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  transition:
    border-color var(--duration-quick) var(--easing-default),
    background var(--duration-quick) var(--easing-default),
    transform var(--duration-quick) var(--easing-default);
}

.brief-cta__action:hover {
  transform: translateY(-1px);
  border-color: var(--text-muted);
  background: color-mix(in oklab, var(--bg-card) 60%, transparent);
}

.brief-cta__action svg {
  inline-size: 16px;
  block-size: 16px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ==========================================================================
   Mocked-feature flag
   ========================================================================== */

.mocked-flag {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 2px var(--space-2);
  background: color-mix(in oklab, var(--color-warning) 15%, transparent);
  color: var(--color-warning);
  border-radius: var(--radius-pill);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

/* ==========================================================================
   Topic-creation credit-cost forecast — informative, non-blocking (§6l)
   ========================================================================== */

.cost-forecast {
  margin-block: var(--space-4);
  padding: var(--space-3) var(--space-4);
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* Over the monthly allowance — a warm tint, never an alarm red. */
.cost-forecast--over {
  background: var(--accent-daily-bg);
  border-color: transparent;
}

/* Segmented usage bar: other topics (green) + this topic (yellow chip),
   the empty track to their right reading as free headroom. Models the
   settings credit-meter track, split into segments. */
.cost-forecast__track {
  display: flex;
  block-size: 8px;
  background: var(--bg-page);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  overflow: hidden;
}

/* Over allowance — the track's right end squares off with the chip, so
   the whole bar visibly runs past where it should stop. */
.cost-forecast--over .cost-forecast__track {
  border-start-end-radius: 0;
  border-end-end-radius: 0;
}

.cost-forecast__seg {
  block-size: 100%;
  transition: inline-size var(--duration-standard) var(--easing-default);
}

/* Other topics — credits already committed, in calm green. */
.cost-forecast__seg--committed {
  background: var(--color-success);
}

/* This topic — the highlight: a rounded bright-yellow chip at the spend
   frontier. It tucks onto the green by exactly the corner radius so the
   green sits behind its rounded left corner (no cream sliver), and its
   min width is kept at twice the radius so a tiny add can never be
   narrower than its own corners (which would let the green behind it
   peek past the right corner). */
.cost-forecast__seg--added {
  background: var(--color-credit-add);
  border-radius: var(--radius-pill);
  margin-inline-start: -4px;
  min-inline-size: 10px;
}

/* Tips over allowance — the chip turns red, its right corners go square
   (rounded left, cut flat right), and it grows to the squared track end
   so the bar reads full. */
.cost-forecast__seg--over {
  background: var(--color-error);
  border-start-end-radius: 0;
  border-end-end-radius: 0;
}

.cost-forecast--over .cost-forecast__seg--added {
  flex-grow: 1;
}

.cost-forecast__legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.cost-forecast__legend li {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.cost-forecast__legend strong {
  color: var(--text-body);
  font-weight: 600;
}

.cost-forecast__swatch {
  inline-size: 10px;
  block-size: 10px;
  border-radius: var(--radius-pill);
  flex: none;
}

.cost-forecast__swatch--committed {
  background: var(--color-success);
}

.cost-forecast__swatch--added {
  background: var(--color-credit-add);
}

/* Free — drawn as the empty track itself: cream with a hairline. */
.cost-forecast__swatch--free {
  background: var(--bg-page);
  border: 1px solid var(--border-subtle);
}

.cost-forecast--over .cost-forecast__swatch--added {
  background: var(--color-error);
}

.cost-forecast__body {
  margin: 0;
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  line-height: var(--leading-snug);
  color: var(--text-muted);
}

.cost-forecast__body strong {
  color: var(--text-body);
  font-weight: 600;
}

/* Cycle-to-date usage caption — sits just beneath the forecast bar on
   the topic detail page. The bar refreshes live as cadence/model are
   edited; this figure is historical, so it lives outside the live region
   and never re-renders. Calm + muted — quiet context, never an alarm. */
.cost-forecast__used {
  margin-block: calc(-1 * var(--space-2)) var(--space-4);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.cost-forecast__used strong {
  color: var(--text-body);
  font-weight: 600;
}

/* ==========================================================================
   Credit meter — the single monitoring-credits meter, on /settings (§6h)
   ========================================================================== */

.credit-meter {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}

.credit-meter__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
}

.credit-meter__label {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}

.credit-meter__count {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-faint);
  white-space: nowrap;
}

.credit-meter__count strong {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  color: var(--text-body);
}

.credit-meter__track {
  block-size: 8px;
  background: var(--bg-page);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  overflow: hidden;
}

.credit-meter__fill {
  block-size: 100%;
  background: var(--color-success);
  border-radius: var(--radius-pill);
  transition: inline-size var(--duration-standard) var(--easing-default);
}

.credit-meter--over .credit-meter__fill {
  background: var(--color-warning);
}

.credit-meter__note {
  margin: 0;
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  line-height: var(--leading-snug);
  color: var(--text-muted);
}

/* Over budget — a warm callout, never an alarm red. */
.credit-meter__note--warn {
  color: var(--text-body);
  background: var(--accent-daily-bg);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
}

.credit-meter__note a {
  color: var(--text-body);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* A scheduled plan change — a quiet line under a hairline. */
.credit-meter__pending {
  margin: 0;
  padding-block-start: var(--space-3);
  border-block-start: 1px solid var(--border-subtle);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
}

/* ==========================================================================
   Nav unread badge
   ========================================================================== */

/* (chat sidebar / brief CTA styles moved into the Chat block above) */

.nav-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  margin-inline-start: 6px;
  font-size: var(--text-xs);
  font-weight: 600;
  border-radius: var(--radius-pill);
  background: var(--color-accent, var(--color-text));
  color: var(--color-background, white);
  vertical-align: middle;
}

/* ============================================================================
 * Bell icon — header dropdown for notifications
 * ========================================================================== */

.bell {
  position: relative;
}

.bell summary {
  list-style: none;
  cursor: pointer;
}

.bell summary::-webkit-details-marker { display: none; }
.bell summary::marker { content: ''; }

.bell__trigger {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: var(--space-2);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-body);
  border: 1px solid transparent;
  transition: background var(--duration-quick) var(--easing-default);
}

.bell__trigger:hover {
  background: var(--accent-weekly-bg);
}

.bell__icon {
  inline-size: 20px;
  block-size: 20px;
}

.bell__sheet {
  position: absolute;
  inset-block-start: calc(100% + var(--space-2));
  inset-inline-end: 0;
  inline-size: 360px;
  max-inline-size: calc(100vw - var(--space-5));
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-modal);
  z-index: 20;
  overflow: hidden;
  transform-origin: top right;
}

/* Subtle entrance on open. The global prefers-reduced-motion rule in
   base.css already clamps animation-duration, so no extra guard here. */
@keyframes bell-sheet-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.bell[open] .bell__sheet {
  animation: bell-sheet-in var(--duration-standard) var(--easing-default);
}

/* Mobile: break out of the bell (which sits mid-right in the actions
   row) and pin a full-width panel below the sticky header, so it never
   hangs off-screen. */
@media (max-width: 767.98px) {
  .bell__sheet {
    position: fixed;
    /* Just under the sticky header: its vertical padding (space-4 ×2) +
       the 38px trigger/avatar row + a small gap. */
    inset-block-start: calc(var(--space-4) * 2 + 38px + var(--space-1));
    inset-inline: var(--space-4);
    inline-size: auto;
    max-inline-size: none;
    max-block-size: calc(100dvh - (var(--space-4) * 2 + 38px) - var(--space-5));
  }
}

.bell-panel__header {
  padding: var(--space-3) var(--space-4);
  border-block-end: 1px solid var(--border-subtle);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}

.bell-panel__loading,
.bell-panel__empty {
  padding: var(--space-5);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
  text-align: center;
}

.bell-panel__list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-block-size: 60vh;
  overflow-y: auto;
}

.bell-panel__item {
  border-block-end: 1px solid var(--border-subtle);
}

.bell-panel__item:last-child {
  border-block-end: 0;
}

.bell-panel__item.is-read .bell-panel__row {
  opacity: 0.7;
}

.bell-panel__row {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  inline-size: 100%;
  padding: var(--space-3) var(--space-4);
  background: transparent;
  border: 0;
  text-align: start;
  cursor: pointer;
  font-family: inherit;
  color: var(--text-body);
}

.bell-panel__row:hover {
  background: var(--accent-weekly-bg);
}

.bell-panel__row-title {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1.3;
}

.bell-panel__row-body {
  font-family: var(--font-body-serif);
  font-size: var(--text-sm);
  color: var(--text-muted);
  line-height: 1.45;
}

.bell-panel__row-time {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  color: var(--text-faint);
  margin-block-start: var(--space-1);
}

.bell-panel__footer {
  padding: var(--space-3) var(--space-4);
  border-block-start: 1px solid var(--border-subtle);
  text-align: center;
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
}

.bell-panel__footer a {
  color: var(--text-body);
  font-weight: 500;
}

.nav-badge--bell {
  position: absolute;
  inset-block-start: -2px;
  inset-inline-end: -2px;
  background: var(--color-error, #b05d5d);
  color: var(--bg-card);
  min-inline-size: 16px;
  block-size: 16px;
  font-size: 10px;
}

/* ============================================================================
 * Inbox — /notifications
 * ========================================================================== */

.inbox-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
}

.inbox-row {
  display: flex;
  align-items: stretch;
  gap: var(--space-2);
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}

.inbox-row.is-unread {
  border-inline-start: 3px solid var(--accent-weekly);
}

.inbox-row.is-read {
  opacity: 0.75;
}

.inbox-row__main {
  flex: 1;
  margin: 0;
}

.inbox-row__button {
  display: block;
  inline-size: 100%;
  background: transparent;
  border: 0;
  padding: var(--space-4) var(--space-5);
  text-align: start;
  cursor: pointer;
  font-family: inherit;
  color: var(--text-body);
}

.inbox-row__button:hover {
  background: var(--accent-weekly-bg);
}

.inbox-row__title {
  font-family: var(--font-body-sans);
  font-size: var(--text-base);
  font-weight: 600;
  margin: 0 0 var(--space-1) 0;
}

.inbox-row__body {
  font-family: var(--font-body-serif);
  font-size: var(--text-sm);
  color: var(--text-muted);
  line-height: 1.5;
  margin: 0 0 var(--space-2) 0;
}

.inbox-row__meta {
  margin: 0;
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  color: var(--text-faint);
}

.inbox-row__dismiss {
  margin: 0;
  display: flex;
  align-items: stretch;
}

.inbox-row__dismiss-button {
  padding: 0 var(--space-4);
  background: transparent;
  border: 0;
  border-inline-start: 1px solid var(--border-subtle);
  cursor: pointer;
  font-size: var(--text-xl);
  color: var(--text-faint);
  transition: color var(--duration-quick) var(--easing-default);
}

.inbox-row__dismiss-button:hover {
  color: var(--color-error);
}

/* ─────────────────────────────────────────────────────────────────
   Onboarding — /welcome/*

   The components below are used only on the /welcome flow + the
   regular Add Topic form. Ported from stylebook/css/components.css.
   The stylebook-only `.stylebook-onboarding__*` annotation classes
   are deliberately not ported — they have no use outside the
   stylebook page.
   ───────────────────────────────────────────────────────────────── */

/* Page background — shared with auth pages so signup → /welcome feels
   continuous (same warm cream + cadence-pastel gradient). */
.onboarding-page {
  min-block-size: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--space-7) var(--space-5) var(--space-9);
  background:
    radial-gradient(ellipse at 20% 0%, var(--accent-weekly-bg) 0%, transparent 50%),
    radial-gradient(ellipse at 100% 100%, var(--accent-daily-bg) 0%, transparent 50%),
    var(--bg-page);
}

.onboarding-header {
  inline-size: 100%;
  max-inline-size: var(--container-content);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-block-end: var(--space-7);
}

.onboarding-step-indicator {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}

.onboarding-step {
  inline-size: 100%;
  max-inline-size: var(--container-step);
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

/* Wide variant — the /welcome/plan step lays four plan cards in a row, so its
   header + body widen past the default 520px step. */
.onboarding-page--wide .onboarding-header,
.onboarding-page--wide .onboarding-step {
  max-inline-size: var(--container-wide);
}

.onboarding-plan-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-4);
  align-items: stretch;
}

@media (max-width: 880px) {
  .onboarding-plan-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 480px) {
  .onboarding-plan-grid { grid-template-columns: 1fr; }
}

/* Compact pricing card in the onboarding context — reuses the .pricing-card
   skin at tighter padding. */
.onboarding-plan-grid .pricing-card { padding: var(--space-5) var(--space-4); }
.onboarding-plan-grid .pricing-card__cta { margin-block-start: auto; }

.onboarding-plan__country-note {
  margin-block-start: var(--space-4);
  text-align: center;
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  color: var(--text-faint);
}

/* Calm "your plan is being set up" note shown on the topic step after a
   checkout hand-off — the activation webhook flips the plan in the background. */
.onboarding-checkout-note {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: color-mix(in oklab, var(--color-success) 9%, transparent);
  color: var(--color-success);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
}

/* Self-serve /billing notice bands. Calm + tinted; colour paired with text. */
.billing-banner {
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-md);
  margin-block-end: var(--space-5);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
}
.billing-banner--success {
  background: color-mix(in oklab, var(--color-success) 10%, transparent);
  color: var(--color-success);
}
.billing-banner--warning {
  background: color-mix(in oklab, var(--color-warning) 12%, transparent);
  color: var(--text-body);
  border: 1px solid color-mix(in oklab, var(--color-warning) 30%, transparent);
}

.onboarding-step__title {
  font-family: var(--font-display);
  font-size: var(--text-4xl);
  font-weight: 600;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  font-variation-settings: 'opsz' 96;
  margin: 0;
}

.onboarding-step__lede {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-md);
  color: var(--text-muted);
  line-height: var(--leading-relaxed);
  margin: 0;
  max-inline-size: 44ch;
}

/* The action stack — primary CTA on top, skip text button below.
   Stacking (not side-by-side) so the user reads the primary first,
   never sees "skip" as a competing equal option. */
.onboarding-actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-3);
  margin-block-start: var(--space-4);
}

.onboarding-actions .button--primary,
.onboarding-actions .button--secondary {
  inline-size: 100%;
  padding-block: var(--space-3);
  font-size: var(--text-md);
}

.onboarding-actions__skip {
  background: transparent;
  border: 0;
  color: var(--text-muted);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  cursor: pointer;
  padding-block: var(--space-2);
  text-align: center;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--border-subtle);
  transition: color var(--duration-quick) var(--easing-default);
}

.onboarding-actions__skip:hover {
  color: var(--text-body);
  text-decoration-color: currentColor;
}

/* While a card capture is in flight (form.is-processing, set by
   revolut-widget.js) the decline link goes inert — the JS also ignores the
   click so the in-flight capture can't be raced by a cancel. */
.is-processing .onboarding-actions__skip {
  pointer-events: none;
  opacity: 0.5;
}

/* The detected-timezone chip — used on step 1 of onboarding. Read-only
   by default, click "change" to expand the inline <select> next to it. */
.tz-chip {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: color-mix(in oklab, var(--accent-weekly-bg) 60%, transparent);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
}

.tz-chip__label {
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.tz-chip__value {
  color: var(--text-body);
  font-weight: 500;
  flex: 1 1 auto;
}

.tz-chip__change {
  background: transparent;
  border: 0;
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0;
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-color: var(--border-subtle);
}

.tz-chip__change:hover {
  color: var(--text-body);
}

/* Expanded variant — the read-only chip swaps for an inline select. */
.tz-chip--expanded {
  background: var(--bg-card);
  border-color: var(--text-muted);
}

.tz-chip__select {
  flex: 1 1 auto;
  min-inline-size: 220px;
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  padding: var(--space-2) var(--space-3);
  background: var(--bg-card);
  color: var(--text-body);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

/* Tier-locked radio row — used on step 2 (delivery window for free users).
   The radio input is replaced by a "Premium" pill; the row stays in the
   document flow so the layout doesn't shift between free and premium. */
.radio-option--locked {
  opacity: 0.85;
  cursor: default;
}

.radio-option--locked .radio-option__hint {
  display: block;
  margin-inline-start: auto;
}

.radio-option__lock-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 2px var(--space-3);
  background: color-mix(in oklab, var(--accent-monthly) 30%, transparent);
  color: var(--text-body);
  border-radius: var(--radius-pill);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.radio-option__lock-pill::before {
  content: '';
  inline-size: 10px;
  block-size: 12px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'><rect x='4' y='11' width='16' height='10' rx='2'/><path d='M8 11V8a4 4 0 0 1 8 0v3'/></svg>") center / contain no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'><rect x='4' y='11' width='16' height='10' rx='2'/><path d='M8 11V8a4 4 0 0 1 8 0v3'/></svg>") center / contain no-repeat;
}

.radio-option__upgrade-link {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  color: var(--text-body);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--text-faint);
}

.radio-option__upgrade-link:hover {
  text-decoration-color: currentColor;
}

/* Tier-helper row — sits under step 2's form, before the actions stack.
   Reads as a hairline + small-caps eyebrow + inline link. */
.tier-helper {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding-block-start: var(--space-4);
  border-block-start: 1px solid var(--border-subtle);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}

.tier-helper__link {
  margin-inline-start: auto;
  color: var(--text-body);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Summary card row — step 3's one-bullet recap of each topic + the
   Tracking-so-far panel on step 2B. Cadence-coloured left edge. */
.summary-bullet {
  display: flex;
  gap: var(--space-4);
  align-items: flex-start;
  padding-block: var(--space-3);
}

.summary-bullet[data-cadence='daily']::before {
  background: var(--accent-daily);
}

.summary-bullet[data-cadence='weekly']::before {
  background: var(--accent-weekly);
}

.summary-bullet[data-cadence='monthly']::before {
  background: var(--accent-monthly);
}

.summary-bullet::before {
  content: '';
  inline-size: 3px;
  align-self: stretch;
  border-radius: 2px;
  flex: 0 0 auto;
}

.summary-bullet__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.summary-bullet__title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  color: var(--text-body);
  margin: 0;
  font-variation-settings: 'opsz' 36;
}

.summary-bullet__meta {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Day-of-week pill row — used for weekly-cadence topics. Single-letter
   buttons in a horizontal radio group. Selected pill fills with the
   cadence accent. The seventh letter (Sunday) repeats S; position is
   the disambiguator, which is fine for the known week sequence. */
.day-pill-row {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}

/* Mobile: tighten the gap between day pills so all seven fit on one row
   even on the narrowest phones (the 8px gap pushed Sunday to a second
   line at ≤375px). Keeps flex-wrap as a safety net for very small
   viewports. */
@media (max-width: 767px) {
  .day-pill-row {
    gap: var(--space-1);
  }
}

.day-pill {
  inline-size: 36px;
  block-size: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-card);
  color: var(--text-body);
  font-family: var(--font-body-sans);
  font-size: var(--text-base);
  font-weight: 500;
  cursor: pointer;
  user-select: none;
  position: relative;
  transition:
    background var(--duration-quick) var(--easing-default),
    border-color var(--duration-quick) var(--easing-default);
}

.day-pill:hover {
  border-color: var(--text-muted);
}

.day-pill input {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  opacity: 0;
  pointer-events: none;
}

.day-pill:has(input:checked),
.day-pill.is-active {
  background: var(--accent-weekly);
  border-color: var(--accent-weekly);
  color: var(--text-body);
  font-weight: 600;
}

.day-pill:has(input:checked)[data-cadence='daily'],
.day-pill.is-active[data-cadence='daily'] {
  background: var(--accent-daily);
  border-color: var(--accent-daily);
}

.day-pill:has(input:checked)[data-cadence='monthly'],
.day-pill.is-active[data-cadence='monthly'] {
  background: var(--accent-monthly);
  border-color: var(--accent-monthly);
}

/* Editorial inset — body-serif italic note that sits between the
   Tracking-so-far panel and the empty form on step 2B. Used to
   illustrate the spread-across-the-week multi-topic pattern. */
.editorial-inset {
  font-family: var(--font-body-serif);
  font-style: italic;
  font-size: var(--text-md);
  color: var(--text-muted);
  line-height: var(--leading-relaxed);
  max-inline-size: 52ch;
  padding-inline: var(--space-4);
  border-inline-start: 2px solid var(--accent-weekly);
  margin-block: var(--space-2);
}

.editorial-inset strong {
  color: var(--text-body);
  font-style: normal;
  font-weight: 600;
}

/* ==========================================================================
   Consent banner — fixed bottom strip, prior-consent gate for cookies
   ========================================================================== */

/* Pinned to the viewport bottom, above modals. Calm and editorial — a
   notice, not an alarm. Hidden by default; the server only renders it for
   visitors who have not yet chosen, and consent.js un-hides it. */
.consent-banner {
  position: fixed;
  inset-block-end: 0;
  inset-inline: 0;
  z-index: 40;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-5);
  background: color-mix(in oklab, var(--bg-card) 92%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-block-start: 1px solid var(--border-subtle);
  box-shadow: var(--shadow-modal);
}

@media (min-width: 768px) {
  .consent-banner {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-6);
    padding: var(--space-5) var(--space-6);
  }
}

.consent-banner__copy {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  max-inline-size: 62ch;
}

.consent-banner__eyebrow {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
}

.consent-banner__text {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--text-muted);
}

.consent-banner__text strong {
  color: var(--text-body);
  font-weight: 600;
}

.consent-banner__text a {
  color: var(--text-body);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Mobile: the two equal pills (Reject all / Accept all) pair on the first
   row and "Save choices" wraps full-width beneath. Desktop: all three inline.
   flex-wrap (not flex-shrink:0) is what keeps a long label from overflowing
   the viewport on a narrow screen. */
.consent-banner__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

@media (min-width: 768px) {
  .consent-banner__actions {
    flex-wrap: nowrap;
    flex-shrink: 0;
  }
}

/* Reject all + Accept all share one class — under PECR, rejecting must be
   exactly as easy as accepting, so the two pills are visually identical.
   white-space:nowrap keeps each label on a single line (no near-circular
   two-line pills); border-box keeps full-width buttons inside the strip. */
.consent-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 1 1 auto;
  box-sizing: border-box;
  white-space: nowrap;
  padding: var(--space-3) var(--space-5);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  font-weight: 500;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-subtle);
  background: var(--bg-card);
  color: var(--text-body);
  cursor: pointer;
  transition:
    border-color var(--duration-quick) var(--easing-default),
    transform var(--duration-quick) var(--easing-default),
    box-shadow var(--duration-quick) var(--easing-default);
}

@media (min-width: 768px) {
  .consent-button {
    flex: 0 0 auto;
  }
}

.consent-button:hover {
  border-color: var(--text-muted);
  transform: translateY(-1px);
  box-shadow: var(--shadow-card);
}

/* "Save choices" — the third action that commits the current toggle mix.
   Quieter than Reject all / Accept all (which stay equal-weight pills per
   PECR) so it reads as the alternative path, not a competing primary. On
   mobile it takes its own full-width row beneath the two pills; inline on
   desktop. */
.consent-button--quiet {
  flex-basis: 100%;
  border-color: transparent;
  background: transparent;
  color: var(--text-muted);
}

@media (min-width: 768px) {
  .consent-button--quiet {
    flex-basis: auto;
  }
}

.consent-button--quiet:hover {
  border-color: var(--border-subtle);
  background: var(--bg-card);
  color: var(--text-body);
}

/* Per-category consent controls — the Analytics + Advertising opt-ins.
   Each category is independent and both default OFF (GDPR is opt-in: no
   pre-ticked boxes). Sits between the copy and the action buttons. */
.consent-banner__controls {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  flex-shrink: 0;
}

@media (min-width: 768px) {
  .consent-banner__controls {
    align-items: flex-end;
  }
}

.consent-banner__categories {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

@media (min-width: 768px) {
  .consent-banner__categories {
    flex-direction: row;
    gap: var(--space-6);
  }
}

.consent-toggle {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  justify-content: space-between;
}

.consent-toggle__text {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.consent-toggle__name {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-body);
  cursor: pointer;
}

.consent-toggle__desc {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* The switch: a transparent checkbox laid over a drawn track + thumb.
   "On" borrows the checkbox accent (ink fill, --text-body) so it reads
   consistently with the form checkboxes elsewhere. */
.consent-switch {
  position: relative;
  flex-shrink: 0;
  inline-size: 40px;
  block-size: 24px;
}

.consent-switch input {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.consent-switch__track {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-subtle);
  background: var(--bg-page);
  /* The track + thumb are drawn after the input in the DOM, so without this
     they paint over it and swallow clicks on the circle. Letting pointer
     events fall through routes every click in the switch to the input. */
  pointer-events: none;
  transition:
    background-color var(--duration-quick) var(--easing-default),
    border-color var(--duration-quick) var(--easing-default);
}

.consent-switch__thumb {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 3px;
  inline-size: 16px;
  block-size: 16px;
  border-radius: 50%;
  background: var(--text-muted);
  transform: translateY(-50%);
  transition:
    inset-inline-start var(--duration-quick) var(--easing-default),
    background-color var(--duration-quick) var(--easing-default);
}

.consent-switch input:hover:not(:checked) + .consent-switch__track {
  border-color: var(--text-muted);
}

.consent-switch input:checked + .consent-switch__track {
  background: var(--text-body);
  border-color: var(--text-body);
}

.consent-switch input:checked + .consent-switch__track .consent-switch__thumb {
  inset-inline-start: 21px;
  background: var(--bg-page);
}

.consent-switch input:focus-visible + .consent-switch__track {
  outline: 2px solid var(--text-body);
  outline-offset: 2px;
}

/* ==========================================================================
   Legal documents — privacy policy, cookie policy (long-form prose)
   ========================================================================== */

.legal-doc {
  padding-block: var(--space-6) var(--space-9);
}

/* Stays visible until legal/DPO sign-off — removing it is not an
   engineering decision. */
.legal-doc__draft-banner {
  margin-block-end: var(--space-6);
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--color-warning);
  border-radius: var(--radius-md);
  background: color-mix(in oklab, var(--color-warning) 12%, var(--bg-page));
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--text-body);
}

.legal-doc__draft-banner strong {
  font-weight: 600;
}

.legal-doc__updated {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
  margin-block-start: var(--space-2);
}

.legal-doc__body {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--text-body);
}

.legal-doc__body h2 {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  margin-block: var(--space-7) var(--space-3);
}

.legal-doc__body h3 {
  font-family: var(--font-body-sans);
  font-size: var(--text-base);
  font-weight: 600;
  margin-block: var(--space-5) var(--space-2);
}

.legal-doc__body p {
  margin-block: var(--space-3);
}

.legal-doc__body ul {
  margin-block: var(--space-3);
  padding-inline-start: var(--space-5);
}

.legal-doc__body li {
  margin-block: var(--space-2);
}

.legal-doc__body a {
  color: var(--text-body);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.legal-doc__body strong {
  font-weight: 600;
}

/* Visible marker for a fact that depends on an unresolved compliance item. */
.legal-doc__todo {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--color-error);
  background: color-mix(in oklab, var(--color-error) 10%, var(--bg-page));
  border-radius: var(--radius-sm);
  padding: 0 var(--space-2);
}

.legal-doc__table-wrap {
  overflow-x: auto;
  margin-block: var(--space-4);
}

.legal-doc__table {
  inline-size: 100%;
  border-collapse: collapse;
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
}

.legal-doc__table th,
.legal-doc__table td {
  text-align: start;
  padding: var(--space-3);
  border-block-end: 1px solid var(--border-subtle);
  vertical-align: top;
}

.legal-doc__table th {
  font-weight: 600;
  color: var(--text-muted);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

/* ───────────────────────────────────────────────────────────────────
   Free-trial surfaces (14-day Pro trial)
   Ported from stylebook/pages/onboarding-trial.html. The trial voice is
   calm forecasting — never urgent, never a banner, never an alarm. Amber
   (--color-warning) is the strongest tone; never red.
   ─────────────────────────────────────────────────────────────────── */

/* Framing-screen timeline: Today → Day 14 → £24. A static, editorial
   milestone track — three soft-tactile stations on a hand-mixed cadence
   gradient (weekly → monthly → amber), each a tinted disc with an accent
   core and a soft lift. No countdown, no draining bar; the amber charge
   station is the anchor. A 3-column grid puts the line through the centres. */
.trial-timeline {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  align-items: start;
  padding: var(--space-6) var(--space-2) var(--space-3);
}
.trial-timeline__track {
  position: absolute;            /* taken out of grid flow */
  inset-block-start: calc(var(--space-6) + 16px);
  inset-inline: calc(100% / 6);  /* spans the centres of the outer columns */
  block-size: 3px;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg,
    var(--accent-weekly) 0%,
    var(--accent-monthly) 50%,
    var(--color-warning) 100%);
}
.trial-timeline__node {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  text-align: center;
}
.trial-timeline__dot {
  position: relative;
  z-index: 1;
  inline-size: 34px;
  block-size: 34px;
  border-radius: 50%;
  background: var(--accent-weekly-bg);
  border: 1.5px solid var(--accent-weekly);
  box-shadow: var(--shadow-card);
  margin-block-end: var(--space-3);
}
.trial-timeline__dot::before {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  inline-size: 10px;
  block-size: 10px;
  border-radius: 50%;
  background: var(--accent-weekly);
}
/* Station 2 (Day 14) — monthly accent. Track is child 1, so the middle
   node is :nth-child(3). */
.trial-timeline__node:nth-child(3) .trial-timeline__dot {
  background: var(--accent-monthly-bg);
  border-color: var(--accent-monthly);
}
.trial-timeline__node:nth-child(3) .trial-timeline__dot::before {
  background: var(--accent-monthly);
}
/* The charge station — amber, larger, a cream core. */
.trial-timeline__node--charge .trial-timeline__dot {
  inline-size: 38px;
  block-size: 38px;
  background: var(--color-warning);
  border-color: var(--color-warning);
}
.trial-timeline__node--charge .trial-timeline__dot::before {
  inline-size: 13px;
  block-size: 13px;
  background: var(--bg-card);
}
.trial-timeline__eyebrow {
  font-family: var(--font-body-sans);
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--text-body);
  line-height: 1.15;
}
.trial-timeline__sub {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
}
@media (max-width: 480px) {
  /* Vertical rail — stations down the left, labels to the right. */
  .trial-timeline {
    grid-template-columns: 1fr;
    row-gap: var(--space-4);
    padding: var(--space-4) var(--space-2);
  }
  .trial-timeline__track {
    inset-block: var(--space-5);
    inset-inline-start: 18px;
    inset-inline-end: auto;
    inline-size: 3px;
    block-size: auto;
    background: linear-gradient(180deg,
      var(--accent-weekly) 0%,
      var(--accent-monthly) 50%,
      var(--color-warning) 100%);
  }
  .trial-timeline__node {
    flex-direction: row;
    align-items: center;
    gap: var(--space-3);
    text-align: start;
  }
  .trial-timeline__dot { margin-block-end: 0; flex: 0 0 auto; }
}

/* Header trial chip — sits where the onboarding step indicator lives.
   Contextual, not promotional: what you have, how long you have it. */
.trial-chip {
  display: inline-flex;
  align-items: center;
  padding: 3px var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  background: color-mix(in oklab, var(--bg-card) 80%, transparent);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Feed greeting trial line — a single calm line under the greeting. */
.greeting__trial {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin-block-start: var(--space-2);
}

/* Brief-footer trial attribution — small, dismissable; the dismissal
   persists across the trial. */
.brief-trial-note {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin-block: var(--space-5) 0;
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-faint);
}
.brief-trial-note__dismiss {
  border: 0;
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  font-size: var(--text-md);
  line-height: 1;
  padding: 0 var(--space-1);
  transition: color var(--duration-quick) var(--easing-default);
}
.brief-trial-note__dismiss:hover { color: var(--text-muted); }

/* In-context upgrade card (cold path) — calm, dismissable, not modal,
   not blocking, shown once. Voice mirrors a quiet footnote. */
.brief-upgrade-card {
  position: relative;
  margin-block: var(--space-6) var(--space-7);
  padding: var(--space-5);
  padding-inline-end: var(--space-7);
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-card);
}
.brief-upgrade-card__close {
  position: absolute;
  inset-block-start: var(--space-3);
  inset-inline-end: var(--space-3);
  inline-size: 28px;
  block-size: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  background: transparent;
  color: var(--text-faint);
  font-size: var(--text-lg);
  line-height: 1;
  cursor: pointer;
  border-radius: var(--radius-pill);
  transition: color var(--duration-quick) var(--easing-default);
}
.brief-upgrade-card__close:hover { color: var(--text-body); }
.brief-upgrade-card__eyebrow {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
  margin-block-end: var(--space-2);
}
.brief-upgrade-card__lede {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--text-body);
  margin: 0 0 var(--space-4);
  max-inline-size: 54ch;
}
.brief-upgrade-card__action {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-5);
  background: transparent;
  color: var(--text-body);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  font-family: var(--font-body-sans);
  font-size: var(--text-base);
  font-weight: 500;
  text-decoration: none;
  transition: border-color var(--duration-quick) var(--easing-default);
}
.brief-upgrade-card__action:hover { border-color: var(--text-body); }

/* Settings · trial state — the briefs-remaining figure borrows the
   credit-meter voice: a big remaining number, a faint cap, a calm line. */
.trial-figure {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-faint);
}
.trial-figure strong {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  color: var(--text-body);
  margin-inline-end: 0.12em;
  font-variation-settings: 'opsz' 36;
}
.trial-note {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
  line-height: var(--leading-snug);
  margin: var(--space-2) 0 0;
}
.trial-note a { color: var(--text-body); text-underline-offset: 2px; }
/* Envelope spent — warm amber, never alarm red. */
.trial-note--warn {
  color: var(--text-body);
  background: var(--accent-daily-bg);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
}
.trial-note__lead { font-weight: 600; color: var(--color-warning); }
.trial-charge-line {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  color: var(--text-body);
  margin: 0;
}

/* The immediate-charge "What you'll pay" amount on the card-details step —
   the charge stated plainly, the same calm discipline as the trial timeline. */
.trial-charge__amount {
  font-family: var(--font-body-sans);
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--text-body);
  margin: 0 0 var(--space-2);
}

/* Small trial affordance under the Pro/Power price on the cold-path plan
   picker — the trial framing lives on the card step; here it's discoverable. */
.onboarding-plan__trial-note {
  margin: 0 0 var(--space-3);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--accent-monthly);
}

/* Trial-end specimens (post-trial confirmation cards). */
.trial-end-card {
  padding: var(--space-5);
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
}
.trial-end-card__label {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0 0 var(--space-2);
}
.trial-end-card__title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  margin: 0 0 var(--space-2);
  font-variation-settings: 'opsz' 30;
}
.trial-end-card__body {
  font-family: var(--font-body-serif);
  font-size: var(--text-base);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
  margin: 0;
}

/* Trial card capture (inline variant) — Revolut's card field mounts inline on
   the framing screen (shown on arrival for the trial states; on click for the
   `used` subscribe). On the trial states the card and the timeline share one
   settings card, split into "Your N days" / "Add your card" groups; these style
   the framing card and the bits around Revolut's iframe. */

/* The framing card sits in the onboarding step's own flex flow, so drop the
   settings-card block margin and let the step gap set the rhythm. (Wins over
   .settings-card by source order.) */
.trial-start {
  margin-block: 0;
}
/* The serif lead under "Add your card" — the cue that the fields are the
   reader's one action. */
.trial-start__lead {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--text-body);
  margin: 0;
}
/* A label + control pair: space-2 between the label and its field; the group's
   own gap (space-3) separates one pair from the next. */
.trial-card__field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
/* The Revolut card iframe mounts here — give it a field-like surface and a
   min-height so the box doesn't collapse before the iframe paints. No explicit
   colour: it inherits --text-body, which revolut-widget.js reads to theme the
   iframe text for light/dark. */
.trial-pay__card {
  padding: var(--space-3) var(--space-4);
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  min-block-size: 44px;
  display: flex;
  align-items: center;
}
/* Shown until the Revolut card field mounts on arrival, then removed by JS. */
.trial-pay__loading {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  font-style: italic;
  color: var(--text-faint);
}
.trial-pay__reassure {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
  text-align: start;
  margin: 0;
}
/* The error line shown if Revolut's card field fails to load or submit. */
.trial-pay__error {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--color-warning);
  text-align: center;
  margin-block-start: var(--space-2);
}
/* The CCR-waiver consent line beneath the card. The card-error paragraph above
   it is hidden in the happy path, so without this the consent text sits flush
   against the card; lift it off to match the card→actions rhythm. */
.trial-consent {
  margin-block-start: var(--space-4);
}

/* The settings subscribe page (/billing/subscribe) — the in-app Free→paid
   card-capture screen, reached from the change-plan picker. One focused
   column at the onboarding step's measure; the card group reuses the trial
   capture styles above. (Graduated from the stylebook prototype in
   pages/settings-subscribe-card.html.) */
.subscribe-stage {
  max-inline-size: 560px;
  margin-inline: auto;
  padding: var(--space-6) var(--space-4) var(--space-10);
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}
.subscribe-stage .page-header {
  padding-inline-start: 0;
}
/* The CTA stands alone — the escape is the back link at the top. */
.subscribe-actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-block-start: var(--space-4);
}
.subscribe-actions .button {
  align-self: stretch;
}

/* ==========================================================================
   Plan & billing — self-serve billing tab + change-plan picker
   The standalone /billing page folds into Settings → Plan & billing; the
   picker lives at /settings/plan. (Graduated from the stylebook prototypes
   in pages/settings.html + pages/plan-change.html.)
   ========================================================================== */

/* A muted flash band — e.g. "Checkout cancelled — no change to your plan." */
.billing-banner--muted {
  background: var(--bg-page);
  border: 1px solid var(--border-subtle);
  color: var(--text-muted);
}

/* Invoices — a quiet list on the billing tab, one row per invoice. */
.invoices-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-1);
}
.invoice-row {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  padding-block: var(--space-2);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
}
.invoice-row + .invoice-row {
  border-block-start: 1px solid var(--border-subtle);
}
.invoice-row__number {
  color: var(--text-body);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.invoice-row__amount {
  color: var(--text-body);
  margin-inline-start: auto;
  font-feature-settings: 'tnum';
}
.invoice-row__date {
  color: var(--text-muted);
  white-space: nowrap;
}

/* ==========================================================================
   Invoice document (/billing/invoices/{id})
   --------------------------------------------------------------------------
   Mobile-first: the base layout is one stacked column; two-column treatments
   are additive at >=560px only. Brieflings leads; the registered entity
   (Kirkton Labs LTD) is quiet fine print in the legal foot. Prints to a clean
   A4 document — see the @media print block at the foot of this file.
   ========================================================================== */

.invoice-page {
  padding-block: var(--space-7);
}

/* Screen-only controls above the sheet. */
.invoice-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  align-items: center;
  margin-block-end: var(--space-5);
}
.invoice-actions__back {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
}

/* The sheet — a single editorial document, generous and quiet. */
.invoice-doc {
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: clamp(var(--space-5), 6vw, var(--space-7));
  color: var(--text-body);
}

/* Masthead — stacked on mobile. Brand on top, then the invoice's identity. */
.invoice-doc__top {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding-block-end: var(--space-5);
  border-block-end: 1px solid var(--border-subtle);
}
.invoice-doc__brand {
  font-family: var(--font-body-sans);
  font-size: var(--text-2xl);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1;
  color: var(--text-body);
}
.invoice-doc__ident {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-3);
}
.invoice-doc__eyebrow {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}
.invoice-doc__number {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  font-feature-settings: 'tnum';
  white-space: nowrap; /* the reference never breaks across lines */
}
.invoice-doc__date {
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
  white-space: nowrap;
}
.invoice-doc__paid {
  display: inline-flex;
  align-items: center;
  padding: 2px var(--space-2);
  border: 1px solid var(--color-success);
  border-radius: var(--radius-pill);
  color: var(--color-success);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

@media (min-width: 560px) {
  .invoice-doc__top {
    flex-direction: row;
    align-items: flex-start;
    justify-content: space-between;
  }
  .invoice-doc__ident {
    flex-direction: column;
    align-items: flex-end;
    text-align: right;
    gap: var(--space-1);
  }
}

/* Billed-to. The issuer lives in the legal foot. */
.invoice-doc__parties { padding-block-start: var(--space-6); }
.invoice-party__label {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-block-end: var(--space-2);
}
.invoice-party__name {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--text-body);
}
.invoice-party__lines {
  margin-block-start: var(--space-1);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--text-muted);
}

/* Line items — a stacked list, not a 4-column table, so it never gets
   squeezed on a phone. Description + period + qty×unit left, amount right. */
.invoice-lines {
  list-style: none;
  margin: var(--space-6) 0 0;
  padding: 0;
}
.invoice-line {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-4);
  padding-block: var(--space-4);
  border-block-start: 1px solid var(--border-subtle);
}
.invoice-line--head {
  padding-block: var(--space-2);
  border-block-start: none;
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.invoice-line__desc {
  font-family: var(--font-body-serif);
  font-size: var(--text-base);
  color: var(--text-body);
}
.invoice-line__meta {
  margin-block-start: var(--space-1);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  color: var(--text-muted);
  font-feature-settings: 'tnum';
}
.invoice-line__amount {
  font-family: var(--font-body-sans);
  font-size: var(--text-base);
  font-feature-settings: 'tnum';
  white-space: nowrap;
}

/* Totals — full width on mobile, hung right with a soft cap on wide. */
.invoice-doc__totals {
  margin-block-start: var(--space-5);
  padding-block-start: var(--space-2);
  border-block-start: 1px solid var(--border-subtle);
}
.invoice-doc__total-row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-2);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
  font-feature-settings: 'tnum';
}
.invoice-doc__total-row--grand {
  margin-block-start: var(--space-1);
  padding-block-start: var(--space-3);
  border-block-start: 1px solid var(--border-subtle);
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  color: var(--text-body);
  letter-spacing: var(--tracking-tight);
}
@media (min-width: 560px) {
  .invoice-doc__totals { margin-inline-start: auto; max-inline-size: 320px; }
}

/* Legal foot — the registered entity, address, company no, contact, VAT note.
   Quiet by design; this is where compliance needs the full registered name to
   appear, not at the top. */
.invoice-doc__legal {
  margin-block-start: var(--space-6);
  padding-block-start: var(--space-5);
  border-block-start: 1px solid var(--border-subtle);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  line-height: var(--leading-normal);
  color: var(--text-muted);
}
.invoice-doc__legal p { margin: 0; }
.invoice-doc__legal p + p { margin-block-start: var(--space-1); }
.invoice-doc__legal a { color: var(--text-muted); }

/* Change-plan picker (/settings/plan) ----------------------------------- */

/* Quiet small-caps back link above the title. */
.change-plan-back {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-block-end: var(--space-3);
}
.change-plan-back:hover { color: var(--text-body); }

/* Intro lede above the grid. */
.change-plan-lede {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
  max-inline-size: 56ch;
  margin-block: var(--space-2) var(--space-5);
}

/* The card for the plan the viewer is already on — a calm accent ring + a
   neutral "Your plan" chip instead of a marketing tag. */
.pricing-card--current {
  border-color: color-mix(in oklab, var(--accent-monthly) 55%, var(--border-subtle));
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent-monthly) 14%, transparent);
}
.pricing-card__tag--current {
  background: var(--bg-page);
  color: var(--text-muted);
  border: 1px solid var(--border-subtle);
}

/* The current plan's CTA is present-but-inert. */
.pricing-card__cta[aria-disabled="true"] {
  opacity: 0.55;
  cursor: default;
  pointer-events: none;
}
/* A downgrade CTA is quieter than an upgrade — a text-weight button. */
.pricing-card__cta--down {
  background: transparent;
  color: var(--text-muted);
  border-color: var(--border-subtle);
}
.pricing-card__cta--down:hover {
  color: var(--text-body);
  border-color: var(--text-muted);
}

/* The two-step downgrade explanation. Calm settings-card skin with a faint
   cadence tint, never an alarm. */
.downgrade-note {
  max-inline-size: var(--container-reading);
  margin-inline: auto;
  margin-block-start: var(--space-7);
  background: color-mix(in oklab, var(--bg-card) 95%, var(--accent-daily) 5%);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  padding: var(--space-6);
}
.downgrade-note__eyebrow {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0 0 var(--space-3);
}
.downgrade-note__title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  margin: 0 0 var(--space-3);
  font-variation-settings: 'opsz' 30;
}
.downgrade-note__steps {
  font-family: var(--font-body-serif);
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--text-body);
  margin: 0 0 var(--space-4);
  padding-inline-start: var(--space-5);
}
.downgrade-note__steps li { margin-block: var(--space-2); }
.downgrade-note__steps strong { font-weight: 600; }

/* ==========================================================================
   Print — the invoice document
   --------------------------------------------------------------------------
   The invoice page (/billing/invoices/{id}) is the one surface designed to
   print. Drop the app chrome and the screen-only controls, then reset the
   sheet to clean black-on-white A4. `.no-print` opts any element out.
   ========================================================================== */
@media print {
  @page { size: A4; margin: 16mm; }
  body { background: #ffffff; }

  .app-header,
  .bottom-tab-bar,
  .marketing-footer,
  .site-colophon,
  .consent-banner,
  .invoice-actions,
  .no-print { display: none !important; }

  /* Reclaim the page — no centred column, no padding. */
  main { margin: 0 !important; padding: 0 !important; }
  .invoice-page {
    max-inline-size: none !important;
    margin: 0 !important;
    padding: 0 !important;
  }

  .invoice-doc {
    border: none;
    border-radius: 0;
    box-shadow: none;
    padding: 0;
    background: #ffffff;
    color: #000000;
  }
  .invoice-doc * { color: #000000 !important; }
  .invoice-doc__eyebrow,
  .invoice-doc__date,
  .invoice-party__label,
  .invoice-party__lines,
  .invoice-line__meta,
  .invoice-doc__total-row,
  .invoice-doc__legal { color: #444444 !important; }
  .invoice-doc__paid { border-color: #444444 !important; color: #444444 !important; }

  /* Don't split these blocks across a page boundary. */
  .invoice-doc__top,
  .invoice-line,
  .invoice-doc__totals { break-inside: avoid; }
}

/* ==========================================================================
   Share a brief — the Share popover on a brief, the share panel (the live
   link + copy), and the public read-only share view. The sheet fetches the
   brief's link each time it opens, so the panel has a single state.
   Material mirrors the account-menu / notification-bell sheets; the entrance
   reuses the @keyframes bell-sheet-in defined above.
   ========================================================================== */

/* Brief-level action row hosting the Share control, under the cover. */
.brief-toolbar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-block: var(--space-5) var(--space-6);
}

/* Share trigger — a quiet pill at secondary-button weight. */
.brief-share { position: relative; }
.brief-share > summary { list-style: none; cursor: pointer; }
.brief-share > summary::-webkit-details-marker { display: none; }
.brief-share > summary::marker { content: ''; }
.brief-share__trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-subtle);
  background: transparent;
  color: var(--text-body);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  font-weight: 500;
  transition:
    border-color var(--duration-quick) var(--easing-default),
    background var(--duration-quick) var(--easing-default);
}
.brief-share__trigger:hover {
  border-color: var(--text-muted);
  background: var(--bg-card);
}
.brief-share__trigger svg {
  inline-size: 16px;
  block-size: 16px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* The sheet — same material as .account-menu__sheet / .bell__sheet. */
.brief-share__sheet {
  position: absolute;
  inset-block-start: calc(100% + var(--space-2));
  inset-inline-start: 0;
  inline-size: 340px;
  max-inline-size: calc(100vw - var(--space-5));
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-modal);
  z-index: 20;
  overflow: hidden;
  transform-origin: top left;
}
.brief-share[open] .brief-share__sheet {
  animation: bell-sheet-in var(--duration-standard) var(--easing-default);
}

/* Mobile: a full-width bottom sheet, the way the bell pins below the header. */
@media (max-width: 767.98px) {
  .brief-share__sheet {
    position: fixed;
    inset-block-start: auto;
    inset-block-end: 0;
    inset-inline: 0;
    inline-size: auto;
    max-inline-size: none;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    border-block-end: 0;
  }
}

/* ---- Share panel: the sheet's state-driven content --------------------- */
.share-panel__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-4) var(--space-3);
  border-block-end: 1px solid var(--border-subtle);
}
.share-panel__title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  color: var(--text-body);
  font-variation-settings: 'opsz' 24;
}
.share-panel__error {
  margin: 0;
  padding: var(--space-3) var(--space-4);
  background: color-mix(in oklab, var(--color-warning) 12%, transparent);
  color: var(--color-warning);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  line-height: var(--leading-snug);
}
.share-panel__body {
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.share-panel__lede {
  font-family: var(--font-body-serif);
  font-size: var(--text-sm);
  color: var(--text-muted);
  line-height: var(--leading-relaxed);
  margin: 0;
}
/* Quiet placeholder shown for the beat between opening the sheet and the
   freshly-minted link swapping in. */
.share-panel__loading {
  margin: 0;
  padding: var(--space-5) var(--space-4);
  text-align: center;
  font-family: var(--font-body-serif);
  font-size: var(--text-sm);
  color: var(--text-muted);
}

/* Read-only link field + copy button. */
.share-link {
  display: flex;
  gap: var(--space-2);
  align-items: stretch;
}
.share-link__url {
  flex: 1;
  min-inline-size: 0;
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-body);
  background: var(--bg-page);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.share-link__url:focus { outline: none; border-color: var(--text-muted); }
.share-link__copy {
  flex-shrink: 0;
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  background: var(--text-body);
  color: var(--bg-page);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  font-weight: 500;
  cursor: pointer;
  transition: background var(--duration-quick) var(--easing-default);
}
.share-link__copy svg {
  inline-size: 15px;
  block-size: 15px;
  flex-shrink: 0;  /* reset.css makes svg display:block — keep icon beside the label */
  stroke: currentColor;
  fill: none;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.share-link__copy-idle { display: inline-flex; align-items: center; gap: var(--space-2); }
.share-link__copy-done { display: none; align-items: center; gap: var(--space-2); }
/* Copied feedback — a calm success tint + label flip, not a loud toast. */
.share-link__copy.is-copied {
  background: var(--color-success);
  color: var(--bg-card);
}
.share-link__copy.is-copied .share-link__copy-idle { display: none; }
.share-link__copy.is-copied .share-link__copy-done { display: inline-flex; }

/* Expiry line. */
.share-panel__expiry {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-body-sans);
  font-size: var(--text-sm);
  color: var(--text-muted);
}
.share-panel__expiry svg {
  inline-size: 15px;
  block-size: 15px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
}
.share-panel__expiry strong { color: var(--text-body); font-weight: 600; }

/* ---- Public read-only view (logged-out visitor) ------------------------ */
/* A thin band under the brand-only header: the read-only tag + a start-free
   CTA, keeping the reading surface itself uncluttered. */
.share-public-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
  max-inline-size: var(--container-reading);
  margin-inline: auto;
  padding: var(--space-4) var(--space-5) 0;
}
.share-public-tag {
  font-family: var(--font-body-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}
.share-public-tag svg {
  inline-size: 13px;
  block-size: 13px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.share-public-body { padding-block: var(--space-5) var(--space-8); }
