/* ============================================================================
   Cut Room -- Vantage public visual system (creator-pivot Wave 5, Task 2)

   The public site is an editing ROOM for vertical video, not a research
   terminal and not a generic AI dashboard. The signature is the Cutline: a
   restrained waveform / edit line interrupted by a vertical playhead. Footage
   gets the space; the accent (coral) is spent only on the one action that
   matters on each screen.

   Self-contained on purpose: the public pages render on THESE tokens + classes,
   not on the research-era main.css component library, so retiring research
   surfaces can never quietly restyle the marketing site.

   TYPE, and read this before touching the stacks below (2026-08-31 design
   audit W0-1). This file has always NAMED Archivo / Instrument Sans / IBM Plex
   Mono, and for months nothing delivered them: no @font-face anywhere in the
   repo, no static/fonts directory, and `document.fonts.size` measuring 0 in
   production, so the whole public surface rendered in the visitor's OS default
   and the design system named an identity it never shipped. The faces are now
   fetched by the shells (base_public.html, plus landing_next.html's inline head
   because that page is standalone) with `display=swap`, so the fallback stacks
   below still paint the first frame and nothing blocks on a webfont: the spec
   §6.6 property is preserved, it is just no longer preserved by shipping
   nothing. This stylesheet itself still imports nothing third-party, which is
   what test_no_render_blocking_third_party_font_import pins.
   ============================================================================ */

/* [hidden] means hidden (2026-08-25). The UA rule loses to any author `display`
   at any specificity, and this file is the ONLY stylesheet the base_public.html
   and base_app_scoped.html shells load -- main.css never reaches them, so the
   global rule has to be repeated here. `.cr-ios-bar[hidden]` further down is
   the page-scoped patch this generalizes; it stays for its history. Full note:
   static/css/main.css section 0. */
[hidden] { display: none !important; }

:root {
  /* -- color: the Cut Room palette (spec §6.2), exact hex ------------------ */
  --cr-stage-black: #0B0D12;   /* the room: page background                  */
  --cr-edit-surface: #161A22;  /* panels, cards, the timeline bed            */
  --cr-edit-raised: #1E2430;   /* a panel lifted above the surface           */
  --cr-canvas-white: #F4F5F7;  /* primary text on black                      */
  --cr-coral: #FF5272;         /* the accent: marks, rules, links, THE dot   */
  --cr-coral-hover: #FF3458;
  /* Porcelain (2026-08-31, owner-picked): the action SLAB. Coral stopped
     being a button fill product-wide on this date; it survives inside the
     primary as a 6px dot, and everywhere else it still means "look here".
     #EDEFF3 on #0D1016 is 16.5:1 -- the room is one ground (--cr-stage-black),
     no light theme to invert for, so these are the tuned values verbatim. */
  --cr-porcelain: #EDEFF3;
  --cr-porcelain-hover: #FFFFFF;
  --cr-porcelain-ink: #0D1016;
  --cr-teal: #2BD4C3;          /* timing, playhead, completed, selected      */
  --cr-amber: #F2B95F;         /* honest warnings + review states only       */

  /* text tiers -- all meet WCAG AA on --cr-stage-black (contrast >= 4.5 for
     body, >= 3.0 for large/secondary). muted #A6ADBB on #0B0D12 ~ 8.0:1. */
  --cr-text: var(--cr-canvas-white);
  --cr-text-dim: #C4CAD4;
  --cr-text-muted: #A6ADBB;
  --cr-text-faint: #7C8698;

  /* borders + hairlines (the crop-frame + timeline-mark lines) */
  --cr-line: rgba(244, 245, 247, 0.10);
  --cr-line-strong: rgba(244, 245, 247, 0.18);
  --cr-coral-line: rgba(255, 82, 114, 0.42);
  --cr-teal-line: rgba(43, 212, 195, 0.42);

  /* -- spacing rhythm (4px base) ------------------------------------------ */
  --cr-space-1: 4px;   --cr-space-2: 8px;   --cr-space-3: 12px;
  --cr-space-4: 16px;  --cr-space-5: 24px;  --cr-space-6: 32px;
  --cr-space-7: 48px;  --cr-space-8: 64px;  --cr-space-9: 96px;

  /* -- typography --------------------------------------------------------- */
  --cr-font-heading: 'Archivo', 'Archivo Expanded', system-ui, -apple-system,
                     'Segoe UI', sans-serif;
  --cr-font-body: 'Instrument Sans', system-ui, -apple-system,
                  'Segoe UI', Roboto, sans-serif;
  --cr-font-mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Consolas,
                  monospace;
  --cr-text-xs: 0.75rem;   --cr-text-sm: 0.875rem;  --cr-text-base: 1rem;
  --cr-text-lg: 1.125rem;  --cr-text-xl: 1.375rem;  --cr-text-2xl: 1.875rem;
  --cr-text-3xl: 2.5rem;   --cr-text-4xl: 3.5rem;

  /* -- radius ------------------------------------------------------------- */
  --cr-radius-sm: 6px;
  --cr-radius: 10px;
  --cr-radius-lg: 16px;
  --cr-radius-pill: 999px;

  /* -- shadow (restrained; supports a lifted panel, never decorative) ----- */
  --cr-shadow: 0 12px 40px -18px rgba(0, 0, 0, 0.7);
  --cr-shadow-coral: 0 8px 28px -12px rgba(255, 82, 114, 0.45);
  /* The porcelain slab's depth (2026-08-31): a top-edge highlight, a tight
     contact shadow, and one long low-opacity drop. Three layers, no color --
     the lift is the only thing left doing the work the coral glow used to do. */
  --cr-shadow-porcelain: inset 0 1px 0 rgba(255, 255, 255, 0.9),
                         0 2px 4px -2px rgba(0, 0, 0, 0.55),
                         0 14px 30px -18px rgba(0, 0, 0, 0.95);

  /* -- motion ------------------------------------------------------------- */
  --cr-motion-fast: 120ms;
  --cr-motion: 200ms;
  --cr-ease: cubic-bezier(0.4, 0, 0.2, 1);

  /* -- layout ------------------------------------------------------------- */
  --cr-content-width: 1080px;
  --cr-content-narrow: 720px;
  --cr-nav-height: 64px;
}

/* ---- base ---------------------------------------------------------------- */
.cr-public {
  margin: 0;
  background: var(--cr-stage-black);
  color: var(--cr-text);
  font-family: var(--cr-font-body);
  font-size: var(--cr-text-base);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
.cr-public h1, .cr-public h2, .cr-public h3 {
  font-family: var(--cr-font-heading);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.08;
  margin: 0;
}
.cr-public a { color: inherit; text-decoration: none; }
.cr-public img, .cr-public video { max-width: 100%; display: block; }
.cr-mono { font-family: var(--cr-font-mono); }

.cr-wrap {
  max-width: var(--cr-content-width);
  margin: 0 auto;
  padding-left: var(--cr-space-5);
  padding-right: var(--cr-space-5);
}
.cr-wrap--narrow { max-width: var(--cr-content-narrow); }
/* 2026-08-31 design audit W0-2: this was the `padding` SHORTHAND with a `0`
   inline axis, and the standard public markup puts both classes on the SAME
   element (`class="cr-section cr-wrap"`). Equal specificity, declared second,
   so the shorthand's `0` silently reset the gutter `.cr-wrap` sets above and
   every card, heading and footnote sat flush on the bezel below the 1080px
   max-width. Measured before the fix at 375 / 768 / 1080: paddingLeft 0px,
   plan card `left 0 width 375`, h1 spanning the full viewport. `padding-block`
   touches only the axis this rule means to own. Never widen it back to the
   shorthand. */
.cr-section { padding-block: clamp(48px, 7vw, 96px); }
.cr-section--surface { background: var(--cr-edit-surface); }
/* 2026-08-31: two stacked section paddings put ~190px of nothing between a
   page's own headline and its first chapter. A section that introduces the one
   below it stops paying for the gap twice. */
.cr-section--flush-b { padding-block-end: 0; }

/* An eyebrow reads like a timecode label, not a marketing tagline. */
.cr-eyebrow {
  font-family: var(--cr-font-mono);
  font-size: var(--cr-text-xs);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cr-teal);
  display: inline-flex;
  align-items: center;
  gap: var(--cr-space-2);
}

/* ---- the Cutline: waveform bars interrupted by a vertical playhead -------- */
.cr-cutline {
  display: flex;
  align-items: center;
  gap: 3px;
  height: 28px;
  position: relative;
}
.cr-cutline i {
  display: block;
  width: 3px;
  border-radius: 2px;
  background: var(--cr-line-strong);
}
.cr-cutline i.cut {
  background: repeating-linear-gradient(
    45deg, var(--cr-coral-line), var(--cr-coral-line) 2px,
    transparent 2px, transparent 5px);
}
.cr-cutline i.keep { background: var(--cr-teal); }
/* the playhead: a thin vertical rule, teal, the one moving mark */
.cr-playhead {
  position: absolute;
  top: -4px;
  bottom: -4px;
  width: 2px;
  background: var(--cr-teal);
  box-shadow: 0 0 10px var(--cr-teal);
}

/* ---- buttons ------------------------------------------------------------- */
.cr-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--cr-space-2);
  min-height: 48px;
  padding: 0 var(--cr-space-5);
  border-radius: 12px; /* 2026-08-31: was --cr-radius (10px). The porcelain
     treatment is tuned at 12, and the ghost beside it takes the same radius
     so a primary/ghost pair still reads as one row rather than two eras. */
  font-family: var(--cr-font-body);
  font-size: var(--cr-text-base);
  font-weight: 600;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background var(--cr-motion) var(--cr-ease),
              border-color var(--cr-motion) var(--cr-ease),
              transform var(--cr-motion-fast) var(--cr-ease);
}
/* The one action on the page (2026-08-31: porcelain, not coral). The dot
   inherits the .cr-btn gap, so it costs the button ~14px of width -- that is
   the measured geometry, and the padding above is balanced against it. */
.cr-btn--primary {
  background: var(--cr-porcelain);
  color: var(--cr-porcelain-ink);
  box-shadow: var(--cr-shadow-porcelain);
  /* 2026-08-31, second pass. .cr-btn is 600, which is the right weight for
     the pale-on-dark ghost beside it; this one inverted its ground last night
     and did not re-weight. Dark ink on a pale slab loses apparent weight to
     irradiation, so 600 here reads lighter than the same 600 did as
     near-white on coral. 700 + a hair of tracking is the same pair the app's
     PrimaryButton ships, and it stays scoped to the primary so the ghost is
     untouched. */
  font-weight: 700;
  letter-spacing: .01em;
}
.cr-btn--primary::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--cr-coral);
}
/* THE DOT WAS PUSHING THE LABEL OFF CENTRE (measured 2026-08-31 in a browser).
   .cr-btn centres its flex row, so the centred thing is the GROUP -- dot + gap
   + label -- which parks the label (6px + 8px) / 2 = 7px right of the button's
   own centre. The eye centres on the words, not on the words-plus-a-dot, so a
   label the CSS believes is centred looks nudged. An empty, same-width ::after
   mirrors the dot across the label and picks up the same row gap, so the row
   is 6+8 | label | 8+6 and the centring lands on the LABEL. Chosen over
   asymmetric padding because it is derived rather than arithmetic and it stays
   correct when the button carries an icon, where the group deserving the
   centre is icon + label. The two widths must stay equal -- pinned in
   tests/test_porcelain_primary.py across all three families. */
.cr-btn--primary::after {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
}
/* THE LINK RESET OUTSPECIFIES THE BUTTON (found 2026-08-31, in a browser, on
   the sign-in page's nav CTA). `.cr-public a { color: inherit }` is (0,1,1)
   and `.cr-btn--primary` is (0,1,0), so EVERY primary that is an <a> -- the
   nav's "Edit a video", the pricing cards, the affiliate CTA -- took its
   colour from the page instead of from this rule. On the coral fill that
   landed on near-white text, which is roughly what was wanted, so the bug sat
   there invisible. On a porcelain fill the same inheritance is #F4F5F7 on
   #EDEFF3: 1.02:1, a button with no readable label on it.
   This restates the ink at (0,1,2) rather than reaching for !important, so a
   page that legitimately needs to override the primary still can. */
.cr-public a.cr-btn--primary { color: var(--cr-porcelain-ink); }
/* THE NAV PILL DOES NOT GET THE DOT (2026-08-31, measured at 320-430).
   The nav's right group is over capacity on a phone and has been for a while:
   logo + EN/ES + Sign in + the CTA need ~371px of a 343px row at 375, so the
   pill already broke to two lines ("Edit a / video", 81x53). The dot costs
   ~14px, which pushed it to THREE lines and grew the whole bar from 64 to 80.
   Suppressing the dot here returns the nav to exactly the geometry it had
   before this pass; the pill is still porcelain, it just spends no coral.
   white-space:nowrap was tried first and is the wrong fix: it holds one line
   and then runs the pill off the right edge below 430px. The pre-existing
   two-line nav pill is a real defect and is worth a proper mobile nav pass;
   it is not this one.
   The ::after goes with it (2026-08-31, second pass): it exists only to
   balance the dot, so suppressing one and keeping the other would push the
   label 7px the OTHER way and re-grow the pill by the 14px this rule was
   written to give back. */
.cr-nav .cr-btn--primary::before,
.cr-nav .cr-btn--primary::after { content: none; }
.cr-btn--primary:hover { background: var(--cr-porcelain-hover); }
.cr-btn--ghost {
  background: transparent;
  color: var(--cr-text);
  border-color: var(--cr-line-strong);
}
.cr-btn--ghost:hover { border-color: var(--cr-teal-line); color: var(--cr-teal); }

/* ---- crop frame: a footage/preview container with corner crop marks ------ */
.cr-frame {
  position: relative;
  background: var(--cr-stage-black);
  border: 1px solid var(--cr-line);
  border-radius: var(--cr-radius-lg);
  overflow: hidden;
}
.cr-frame::before, .cr-frame::after {
  content: '';
  position: absolute;
  width: 18px; height: 18px;
  border: 2px solid var(--cr-teal-line);
  pointer-events: none;
}
.cr-frame::before { top: 10px; left: 10px; border-right: 0; border-bottom: 0; }
.cr-frame::after { bottom: 10px; right: 10px; border-left: 0; border-top: 0; }

/* a panel (feature / step / faq card) -- flat surface, hairline, no glass */
.cr-panel {
  background: var(--cr-edit-surface);
  border: 1px solid var(--cr-line);
  border-radius: var(--cr-radius);
  padding: var(--cr-space-5);
}

/* ---- FAQ disclosure rows (2026-08-31 design audit) ------------------------
   A <summary> keeps the UA's raw disclosure triangle unless BOTH `list-style`
   and the WebKit marker pseudo-element are cleared: Safari ignored `list-style`
   on summary for years and only honours ::-webkit-details-marker, so dropping
   either half puts the triangle back on half the visitors. Six FAQ rows on
   /subscribe shipped that triangle while the landing page one click away drew a
   chevron, which is one site with two disclosure markers. The chevron below is
   that same figure rebuilt on this file's tokens. */
.cr-faq summary {
  list-style: none;
  cursor: pointer;
  position: relative;
  padding-right: var(--cr-space-6);
  font-weight: 600;
  font-size: var(--cr-text-base);
}
.cr-faq summary::-webkit-details-marker { display: none; }
.cr-faq summary::after {
  content: '';
  position: absolute;
  right: 4px;
  top: 50%;
  width: 9px;
  height: 9px;
  border-right: 2px solid var(--cr-text-faint);
  border-bottom: 2px solid var(--cr-text-faint);
  transform: translateY(-70%) rotate(45deg);
  transition: transform var(--cr-motion-fast) var(--cr-ease);
}
.cr-faq details[open] summary { color: var(--cr-coral); }
.cr-faq details[open] summary::after { transform: translateY(-30%) rotate(225deg); }

/* ---- a horizontally scrollable frame (2026-08-31 design audit) ------------
   The plan comparison table has a 520px min-width and lives in a 375px
   viewport, and `overflow-x:auto` alone is an invisible affordance on macOS and
   iOS: overlay scrollbars stay hidden until you are ALREADY scrolling, which is
   the one moment the hint is useless. So a phone visitor simply never learned
   the Creator and Studio columns existed. Styling ::-webkit-scrollbar opts the
   element out of overlay behaviour and draws a permanent hairline rail; the
   inset edge shadow (narrow viewports only, where the table actually overflows)
   says the content continues past the right edge. No gradient anywhere: spec
   §6.2 keeps the only gradient in this system on the CUT hatch, and
   test_no_generic_ai_gradient_identity enforces that. */
.cr-scroll-x {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--cr-line-strong) transparent;
}
.cr-scroll-x::-webkit-scrollbar { height: 6px; }
.cr-scroll-x::-webkit-scrollbar-track {
  background: var(--cr-line);
  border-radius: var(--cr-radius-pill);
}
.cr-scroll-x::-webkit-scrollbar-thumb {
  background: var(--cr-line-strong);
  border-radius: var(--cr-radius-pill);
}
@media (max-width: 760px) {
  .cr-scroll-x { box-shadow: inset -22px 0 18px -20px rgba(0, 0, 0, 0.92); }
}

/* ---- nav ----------------------------------------------------------------- */
.cr-nav {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  gap: var(--cr-space-5);
  min-height: var(--cr-nav-height);
  padding: 0 var(--cr-space-5);
  background: rgba(11, 13, 18, 0.86);
  border-bottom: 1px solid var(--cr-line);
  backdrop-filter: blur(10px);
}
.cr-nav__logo {
  display: inline-flex;
  align-items: center;
  gap: var(--cr-space-2);
  font-family: var(--cr-font-heading);
  font-weight: 800;
  font-size: var(--cr-text-lg);
  letter-spacing: -0.02em;
}
.cr-nav__links {
  display: flex;
  align-items: center;
  gap: var(--cr-space-1);
  margin-left: var(--cr-space-4);
}
.cr-nav__links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--cr-space-3);
  font-size: var(--cr-text-sm);
  font-weight: 500;
  color: var(--cr-text-muted);
  border-radius: var(--cr-radius-sm);
}
.cr-nav__links a:hover { color: var(--cr-text); }
.cr-nav__right { margin-left: auto; display: flex; align-items: center; gap: var(--cr-space-3); }
.cr-nav__signin { color: var(--cr-text-muted); font-size: var(--cr-text-sm); font-weight: 500; padding: 0 var(--cr-space-2); min-height: 44px; display: inline-flex; align-items: center; }
.cr-nav__signin:hover { color: var(--cr-text); }
@media (max-width: 860px) { .cr-nav__links { display: none; } }
/* September 5, 2026: translated auth actions exceed one phone-width row.
   Give branding/language and account actions their own rows, keeping every
   action visible without squeezing the Spanish CTA into three lines. */
@media (max-width: 600px) {
  .cr-nav {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 4px 12px;
    padding: 8px 16px;
  }
  .cr-nav__right { display: contents; }
  .cr-nav__logo { grid-area: 1 / 1; }
  .cr-nav__language { grid-area: 1 / 2; justify-self: end; min-height: 44px; }
  .cr-nav__language a { display: inline-flex; align-items: center; min-height: 44px; padding: 0 4px; }
  .cr-nav__signin { grid-area: 2 / 1; justify-self: start; white-space: nowrap; }
  .cr-nav .cr-btn--primary { grid-area: 2 / 2; justify-self: end; font-size: 14px; white-space: nowrap; }
}

/* ---- footer -------------------------------------------------------------- */
.cr-footer {
  border-top: 1px solid var(--cr-line);
  padding: var(--cr-space-7) var(--cr-space-5);
  display: flex;
  flex-wrap: wrap;
  gap: var(--cr-space-4) var(--cr-space-6);
  align-items: center;
  justify-content: space-between;
}
.cr-footer__links { display: flex; flex-wrap: wrap; gap: var(--cr-space-4); }
.cr-footer__links a { color: var(--cr-text-muted); font-size: var(--cr-text-sm); min-height: 44px; display: inline-flex; align-items: center; }
.cr-footer__links a:hover { color: var(--cr-text); }
.cr-disclosure { color: var(--cr-text-faint); font-size: var(--cr-text-xs); max-width: 520px; line-height: 1.5; }

/* ---- focus (visible, keyboard-first; spec §6.6) -------------------------- */
.cr-public a:focus-visible,
.cr-public button:focus-visible,
.cr-public input:focus-visible,
.cr-public summary:focus-visible,
.cr-public [tabindex]:focus-visible {
  outline: 3px solid var(--cr-teal);
  outline-offset: 2px;
  border-radius: var(--cr-radius-sm);
}

/* ---- motion: playhead sweep, staged only, and OFF under reduced-motion --- */
@keyframes cr-playhead-sweep {
  from { left: 0%; }
  to { left: 100%; }
}
.cr-cutline--live .cr-playhead {
  animation: cr-playhead-sweep 3.2s var(--cr-ease) infinite alternate;
}

@media (prefers-reduced-motion: reduce) {
  .cr-public *,
  .cr-public *::before,
  .cr-public *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .cr-cutline--live .cr-playhead { animation: none; left: 62%; }
}

/* prevent horizontal page scroll; wide media scrolls inside its own frame */
.cr-public { overflow-x: hidden; }

/* ---------------------------------------------------------------------------
   iOS announcement bar (2026-07-28, owner request)
   Sits above the nav on every public page. Teal, not coral: coral is THE action
   colour and is reserved for the primary CTA, so an announcement that shouted
   in coral would compete with the button it is trying to send people to.
   --------------------------------------------------------------------------- */
.cr-ios-bar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--cr-space-4);
  flex-wrap: wrap;
  padding: var(--cr-space-3) var(--cr-space-5);
  /* FLAT, not a gradient (2026-07-28). The first version faded teal across the
     bar, which reads as decoration and breaks spec 6.2: the only gradient in
     this system is the diagonal hatch on a CUT segment, and
     test_no_generic_ai_gradient_identity enforces that. A single tint is also
     truer to the room: surfaces here are flat and separated by hairlines. */
  background: rgba(43, 212, 195, 0.10);
  border-bottom: 1px solid var(--cr-teal-line);
  position: relative;
}

.cr-ios-bar[hidden] { display: none; }

.cr-ios-bar__text {
  margin: 0;
  color: var(--cr-text-dim);
  font-size: var(--cr-text-sm);
  line-height: 1.45;
  text-align: center;
}

.cr-ios-bar__tag {
  display: inline-block;
  margin-right: var(--cr-space-2);
  padding: 2px 8px;
  border: 1px solid var(--cr-teal-line);
  border-radius: 999px;
  color: var(--cr-teal);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}

.cr-ios-bar__cta {
  color: var(--cr-teal);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
  white-space: nowrap;
}

.cr-ios-bar__cta:hover { color: var(--cr-canvas-white); }

/* 44px minimum target: this sits next to a link, and a close button that needs
   a precise tap is how a dismissible banner becomes a permanent one on a
   phone. */
.cr-ios-bar__close {
  position: absolute;
  right: var(--cr-space-3);
  top: 50%;
  transform: translateY(-50%);
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  color: var(--cr-text-faint);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}

.cr-ios-bar__close:hover { color: var(--cr-text); }

.cr-ios-bar__close:focus-visible,
.cr-ios-bar__cta:focus-visible {
  outline: 2px solid var(--cr-teal);
  outline-offset: 2px;
}

/* The close button overlaps centred text once the bar wraps, so below the
   wrap point the content stops pretending it is one centred line. */
@media (max-width: 640px) {
  .cr-ios-bar {
    justify-content: flex-start;
    text-align: left;
    padding-right: 56px;
  }
  .cr-ios-bar__text { text-align: left; }
  /* The second sentence is the nice-to-have. On a phone it pushed the bar to
     three lines and 130px, which is a sixth of the viewport spent before the
     reader reaches the nav. The headline claim survives; the elaboration goes. */
  .cr-ios-bar__more { display: none; }
}

/* ============================================================================
   PRICING: the one offer story (web Wave 1, 2026-08-31)

   These selectors are the shared vocabulary behind templates/_partials/
   plan_cards.html, which /subscribe renders and which the landing renders
   through its own inline twin. They are TOP LEVEL, not scoped under
   `.cr-public`, for the same reason `.cr-btn` and `.cr-panel` are: the landing
   is a standalone document with its own stage colour and must be able to link
   this sheet without taking the body class.

   NO DECORATIVE GRADIENT LIVES HERE, and the ban is enforced by a grep, so do
   not write the banned function name even in a comment:
   test_no_generic_ai_gradient_identity reads this whole file as text. A raised
   pricing card is the single most likely place for a decorative wash to
   reappear, so the recommended plan is raised with a border, a shadow and one
   step of surface elevation instead.
   ============================================================================ */

.cr-offerbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--cr-space-3);
  background: rgba(43, 212, 195, 0.06);
  border: 1px solid var(--cr-teal-line);
  border-radius: var(--cr-radius-pill);
  padding: var(--cr-space-3) var(--cr-space-5);
  margin: 0 auto var(--cr-space-6);
  max-width: max-content;
  text-align: center;
}
.cr-offerbar__b {
  font-family: var(--cr-font-mono);
  font-size: var(--cr-text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cr-teal);
}
.cr-offerbar__t { font-size: var(--cr-text-sm); color: var(--cr-text-dim); }
/* A pill radius is a pill only while the content is one line. Once the
   sentence and the button wrap to three, the same radius draws an oval around
   a paragraph, so below the wrap point it becomes a panel. */
@media (max-width: 640px) {
  .cr-offerbar { border-radius: var(--cr-radius-lg); max-width: 100%; }
}
.cr-btn--sm { min-height: 38px; padding: 0 var(--cr-space-4); font-size: var(--cr-text-sm); }

/* `align-items: stretch` is what makes the cards equal height. The retired
   `min-height: 2.6em` on the tagline was doing that job badly: it reserved a
   second line on every tier whose sentence fit on one (audit defect 7). */
.cr-plans {
  display: grid;
  gap: var(--cr-space-4);
  grid-template-columns: repeat(auto-fit, minmax(255px, 1fr));
  align-items: stretch;
  max-width: 1080px;
  margin: 0 auto;
}
.cr-plan {
  display: flex;
  flex-direction: column;
  background: var(--cr-edit-surface);
  border: 1px solid var(--cr-line);
  border-radius: var(--cr-radius-lg);
  padding: var(--cr-space-6) var(--cr-space-5);
}
.cr-plan--pick {
  border-color: var(--cr-coral-line);
  background: var(--cr-edit-raised);
  box-shadow: var(--cr-shadow-coral);
}
/* Raised only above the wrap point. Below it the grid is one column in source
   order with the recommended plan first, and a card lifted out of a single
   column reads as a rendering fault rather than as emphasis. */
@media (min-width: 880px) { .cr-plan--pick { transform: translateY(-8px); } }
/* Below the raise, the recommended plan is simply FIRST. A phone reads the
   grid in source order and the first card is the one that gets read, so the
   emphasis has to change shape rather than disappear. */
@media (max-width: 879px) {
  .cr-plans { display: flex; flex-direction: column; }
  .cr-plan--pick { order: -1; }
}
.cr-plan__flag {
  font-family: var(--cr-font-mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cr-coral);
  margin-bottom: var(--cr-space-3);
}
.cr-plan__name {
  font-family: var(--cr-font-heading);
  font-weight: 800;
  font-size: var(--cr-text-lg);
}
.cr-plan__price {
  display: flex;
  align-items: baseline;
  gap: 7px;
  margin: var(--cr-space-3) 0 var(--cr-space-1);
}
/* The price at display size with TABULAR figures, in the HEADING face and not
   the mono one. This is the real fix for audit defect 5, the amount that read
   as "$9 . 99": in a monospaced face the decimal point gets a full character
   cell of its own, so no amount of negative tracking closes the gap without
   also crushing the digits. Tabular figures keep the columns aligned across
   the three cards, which is the only thing the mono face was buying here. */
.cr-plan__amount {
  font-family: var(--cr-font-heading);
  font-size: var(--cr-text-2xl);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.cr-plan__period { color: var(--cr-text-muted); font-size: var(--cr-text-sm); }
.cr-plan__risk { color: var(--cr-text-muted); font-size: var(--cr-text-xs); margin: 0; }
.cr-plan__tag {
  color: var(--cr-text-dim);
  font-size: var(--cr-text-sm);
  margin: var(--cr-space-3) 0 var(--cr-space-4);
}
.cr-plan__more { margin-bottom: var(--cr-space-4); }
.cr-plan__more summary {
  font-family: var(--cr-font-mono);
  font-size: var(--cr-text-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--cr-text-faint);
  cursor: pointer;
  list-style: none;
  padding: var(--cr-space-2) 0;
}
.cr-plan__more summary::-webkit-details-marker { display: none; }
.cr-plan__more summary::after { content: '+'; float: right; font-size: 13px; line-height: 1; }
.cr-plan__more[open] summary::after { content: '-'; }
.cr-plan__more summary:hover { color: var(--cr-text); }
.cr-plan__list {
  list-style: none;
  padding: 0;
  margin: var(--cr-space-3) 0 0;
  display: flex;
  flex-direction: column;
  gap: var(--cr-space-2);
}
.cr-plan__list li {
  display: flex;
  gap: var(--cr-space-2);
  font-size: var(--cr-text-sm);
  color: var(--cr-text-dim);
  align-items: flex-start;
}
.cr-plan__list li i { color: var(--cr-teal); font-style: normal; line-height: 1.6; }
.cr-plan__cta { width: 100%; box-sizing: border-box; margin-top: auto; }
.cr-plan__ann {
  font-size: var(--cr-text-xs);
  color: var(--cr-text-faint);
  margin-top: var(--cr-space-3);
  text-align: center;
}

/* The pinned CTA. It is a phone affordance only: on a narrow screen the cards
   stack to well over one viewport, so the buy action is otherwise off screen
   for the whole scroll. It carries the SAME href the recommended card carries
   rather than a second checkout path that can drift from the grid. */
.cr-pincta { display: none; }
@media (max-width: 640px) {
  .cr-pincta {
    display: flex;
    position: sticky;
    bottom: 0;
    z-index: 20;
    align-items: center;
    justify-content: space-between;
    gap: var(--cr-space-3);
    background: var(--cr-edit-raised);
    border-top: 1px solid var(--cr-line-strong);
    padding: var(--cr-space-3) var(--cr-space-4);
    padding-bottom: calc(var(--cr-space-3) + env(safe-area-inset-bottom));
  }
  .cr-pincta__plan { display: flex; flex-direction: column; line-height: 1.25; }
  .cr-pincta__plan b { font-size: var(--cr-text-sm); }
  .cr-pincta__plan span {
    font-family: var(--cr-font-mono);
    font-size: var(--cr-text-xs);
    font-variant-numeric: tabular-nums;
    color: var(--cr-text-muted);
  }
  .cr-pincta__go { min-height: 44px; }
  /* The grid keeps its own clearance so the bar never covers the last card. */
  .cr-plans { padding-block-end: 72px; }
}

/* ============================================================================
   CHASSIS (web Wave 1, 2026-08-31)

   The landing page was the only public surface anybody DESIGNED. The other
   five were assembled from three panels and a button, which is why the audit
   read them as a different site: numbered section markers, the two-column
   alternating band, the measured-figure grid and the honesty primitives all
   existed, on exactly one page, in an inline style block nothing else can
   reach. This section is that vocabulary, moved where the rest of the site can
   speak it.

   Direction of travel is landing -> shared, never the reverse.

   TOP LEVEL, not scoped under `.cr-public`, for the same reason `.cr-btn` and
   `.cr-panel` are not: a standalone document has to be able to link this sheet
   without adopting the body class, which would reskin its ground.

   Two rules changed shape on the way over, and both changes are the same
   change: the banned decorative gradient function does not appear in this
   file (a grep enforces it, see the note in the pricing section above), so the
   marker's fading hairline is a solid line at reduced opacity and the raised
   plan card is a flat elevated surface. A 1px rule's fade is invisible at
   reading distance anyway. Radial atmosphere and the repeating hatch are not
   the banned function and port unchanged.
   ============================================================================ */

/* ---- numbered section markers ------------------------------------------- */
.cr-marker {
  display: flex;
  align-items: center;
  gap: var(--cr-space-4);
  margin-bottom: var(--cr-space-6);
}
.cr-marker__n {
  font-family: var(--cr-font-mono);
  font-size: var(--cr-text-xs);
  letter-spacing: 0.16em;
  color: var(--cr-coral);
  border: 1px solid var(--cr-coral-line);
  border-radius: var(--cr-radius-pill);
  padding: 4px 10px;
  white-space: nowrap;
}
.cr-marker__t {
  font-family: var(--cr-font-mono);
  font-size: var(--cr-text-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--cr-text-faint);
}
.cr-marker__line { flex: 1; height: 1px; background: var(--cr-line-strong); opacity: 0.5; }

/* ---- atmosphere: an opt-in bloom, so any section can carry the hero's air */
.cr-atmos--warm, .cr-atmos--center { position: relative; overflow: hidden; }
.cr-atmos--warm > *, .cr-atmos--center > * { position: relative; }
.cr-atmos--warm::before {
  content: '';
  position: absolute;
  inset: -30% 40% 40% -25%;
  background: radial-gradient(closest-side, rgba(255, 82, 114, 0.16), transparent 70%);
  pointer-events: none;
}
.cr-atmos--center::before {
  content: '';
  position: absolute;
  left: 50%;
  top: -10%;
  width: min(760px, 120%);
  height: 120%;
  transform: translateX(-50%);
  background: radial-gradient(closest-side, rgba(255, 82, 114, 0.14), transparent 72%);
  pointer-events: none;
}

/* A film-perf rail down the right edge. Desktop only: at phone widths it is a
   34px stripe of a 375px viewport, which is decoration charging rent. */
.cr-perf-rail::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: 34px;
  background: repeating-linear-gradient(180deg, transparent 0 22px,
                                        var(--cr-line) 22px 23px);
  opacity: 0.7;
  pointer-events: none;
  display: none;
}
@media (min-width: 940px) { .cr-perf-rail::after { display: block; } }

/* ---- the Cutline at reading scale ---------------------------------------
   The base .cr-cutline is 28px tall with 3px bars, which is a signature mark
   in a text line. Sat next to a 3rem headline as the hero's whole right
   column, that is the "rendering glitch" the audit measured: bars too small to
   read as a waveform, floating in a 200x60 box. The bars also sit on a shared
   BASELINE at these sizes, because a row of centred dashes is a dashed rule,
   not an edit. */
.cr-cutline--lg { height: 72px; gap: 5px; align-items: flex-end; }
.cr-cutline--lg i { width: 6px; }
.cr-cutline--xl { height: 120px; gap: 7px; align-items: flex-end; }
.cr-cutline--xl i { width: 8px; }

/* ---- the measured-figure grid ------------------------------------------- */
.cr-cells { display: grid; grid-template-columns: 1fr; gap: var(--cr-space-4); }
@media (min-width: 560px) {
  .cr-cells { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
}
.cr-cell { border-left: 2px solid var(--cr-teal-line); padding: 2px 0 2px var(--cr-space-4); }
.cr-cell b {
  display: block;
  font-family: var(--cr-font-mono);
  font-size: clamp(1.25rem, 4.6vw, 1.5rem);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--cr-text);
  letter-spacing: -0.02em;
  white-space: nowrap;
}
.cr-cell span {
  display: block;
  font-size: var(--cr-text-sm);
  color: var(--cr-text-muted);
  margin-top: 4px;
  line-height: 1.45;
}

/* ---- the honesty primitives ---------------------------------------------
   Three shapes, so a page cannot invent a fourth one for "we have no number
   here yet". `.cr-numline` states a measured pair; `.cr-noline` says the thing
   is measured without borrowing a figure; `.cr-honest` says in plain words
   what we do not know. */
.cr-numline {
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  margin-top: var(--cr-space-5);
  font-family: var(--cr-font-mono);
  font-variant-numeric: tabular-nums;
  border-left: 2px solid var(--cr-coral);
  padding-left: 14px;
}
.cr-numline b { font-size: 1.5rem; color: var(--cr-text); letter-spacing: -0.02em; }
.cr-numline span {
  font-size: var(--cr-text-sm);
  color: var(--cr-text-muted);
  max-width: 34ch;
  line-height: 1.5;
}
.cr-noline {
  margin-top: var(--cr-space-5);
  font-family: var(--cr-font-mono);
  font-size: var(--cr-text-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--cr-text-faint);
  border-left: 2px solid var(--cr-line-strong);
  padding-left: 14px;
}
.cr-honest {
  margin-top: var(--cr-space-5);
  font-size: var(--cr-text-sm);
  color: var(--cr-text-faint);
  max-width: 42ch;
  border-left: 2px solid var(--cr-line-strong);
  padding-left: 14px;
  line-height: 1.6;
}

/* ---- the alternating feature band ---------------------------------------
   This is what replaces the four-up card row on the feature pages. A card row
   makes four claims the same size and lets the shortest one set every card's
   height; a band gives the first two claims room and lets the rest be a
   text strip that has no height to ragged. */
.cr-feat {
  display: grid;
  gap: var(--cr-space-6);
  align-items: center;
  padding: var(--cr-space-7) 0;
  border-top: 1px solid var(--cr-line);
}
@media (min-width: 900px) {
  .cr-feat { grid-template-columns: 1fr 1fr; gap: var(--cr-space-8); padding: var(--cr-space-8) 0; }
  .cr-feat--flip .cr-feat__art { order: -1; }
}
.cr-feat--open { border-top: 0; }
.cr-feat h3 { font-size: clamp(1.5rem, 4vw, 2.05rem); letter-spacing: -0.025em; }
.cr-feat p { color: var(--cr-text-muted); margin-top: var(--cr-space-4); max-width: 48ch; }
.cr-feat__art {
  background: var(--cr-edit-surface);
  border: 1px solid var(--cr-line);
  border-radius: var(--cr-radius-lg);
  padding: var(--cr-space-5);
}

/* ---- the quiet tool strip ------------------------------------------------
   A tool is a top-bordered text block, not a fixed-height card, which is why
   this shape has no ragged baselines to fix. */
.cr-tools {
  display: grid;
  gap: var(--cr-space-4);
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}
.cr-tool { border-top: 1px solid var(--cr-line-strong); padding-top: var(--cr-space-4); }
.cr-tool b {
  display: block;
  font-family: var(--cr-font-heading);
  font-size: var(--cr-text-base);
  font-weight: 800;
  letter-spacing: -0.01em;
}
.cr-tool span {
  display: block;
  color: var(--cr-text-muted);
  font-size: var(--cr-text-sm);
  margin-top: 6px;
}

/* ---- numbered steps, left aligned ---------------------------------------
   The centred variant was one of three alignment systems on one page. Two of
   them are deleted rather than reconciled. */
.cr-steps { display: flex; flex-direction: column; gap: var(--cr-space-3); }
.cr-steps li { display: flex; gap: var(--cr-space-4); align-items: flex-start; }
.cr-steps__n {
  font-family: var(--cr-font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--cr-coral);
  font-weight: 700;
}

/* ---- the affiliate earnings calculator ----------------------------------
   Every figure it prints is arithmetic on a real plan price and the real
   commission rates from app/routes/affiliates.py. There is no
   follower-to-referral conversion rate in this product, so the widget never
   turns an audience size into a dollar figure: that would be fabricating the
   only number that matters. */
.cr-aff-calc {
  display: grid;
  gap: var(--cr-space-5);
  background: var(--cr-edit-surface);
  border: 1px solid var(--cr-line);
  border-radius: var(--cr-radius-lg);
  padding: var(--cr-space-6);
}
@media (min-width: 860px) { .cr-aff-calc { grid-template-columns: 1fr 1fr; gap: var(--cr-space-7); } }
.cr-aff-calc__field { display: block; margin-bottom: var(--cr-space-5); }
.cr-aff-calc__field > span {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-family: var(--cr-font-mono);
  font-size: var(--cr-text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cr-text-faint);
  margin-bottom: var(--cr-space-2);
}
.cr-aff-calc__field b {
  font-size: var(--cr-text-lg);
  color: var(--cr-text);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}
.cr-aff-calc input[type="range"] { width: 100%; accent-color: var(--cr-coral); }
.cr-aff-calc__seg { display: flex; flex-wrap: wrap; gap: var(--cr-space-2); }
.cr-aff-calc__seg button {
  flex: 1 1 auto;
  min-height: 44px;
  background: transparent;
  border: 1px solid var(--cr-line-strong);
  border-radius: var(--cr-radius);
  color: var(--cr-text-dim);
  font-family: inherit;
  font-size: var(--cr-text-sm);
  font-weight: 600;
  cursor: pointer;
}
.cr-aff-calc__seg button[aria-pressed="true"] {
  border-color: var(--cr-coral-line);
  color: var(--cr-text);
  background: var(--cr-edit-raised);
}
.cr-aff-calc__out b {
  display: block;
  font-family: var(--cr-font-mono);
  font-size: clamp(2rem, 7vw, 3rem);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  line-height: 1;
}
.cr-aff-calc__out p { color: var(--cr-text-muted); font-size: var(--cr-text-sm); margin-top: var(--cr-space-3); }
.cr-aff-calc__rate {
  display: inline-block;
  font-family: var(--cr-font-mono);
  font-size: var(--cr-text-xs);
  letter-spacing: 0.1em;
  color: var(--cr-teal);
  border: 1px solid var(--cr-teal-line);
  border-radius: var(--cr-radius-pill);
  padding: 3px 10px;
  margin-top: var(--cr-space-4);
}
.cr-fineprint {
  color: var(--cr-text-faint);
  font-size: var(--cr-text-xs);
  line-height: 1.7;
  max-width: 72ch;
}

/* ---- small shared utilities the affiliate rebuild needs ------------------
   Added 2026-08-31 so that page can carry ZERO inline style attributes and
   zero hex literals. It had 24 of the former and 7 of the latter, which is how
   a page ends up with three teals none of which is the token. */
.cr-center { text-align: center; }
.cr-lede {
  font-size: var(--cr-text-lg);
  color: var(--cr-text-dim);
  max-width: 54ch;
  line-height: 1.6;
  margin: var(--cr-space-4) 0 var(--cr-space-6);
}
.cr-2col { display: grid; gap: var(--cr-space-6); align-items: center; }
@media (min-width: 900px) { .cr-2col { grid-template-columns: 1.05fr 0.95fr; gap: var(--cr-space-8); } }
.cr-trio { display: grid; gap: var(--cr-space-4); grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
/* One treatment for all three figures. The old page coloured the FIRST stat
   and left the other two plain, which reads as emphasis nobody chose. */
/* The heading face, not the mono one: two of these three figures are WORDS,
   and a monospaced "Every month" wraps into a second line that lines up with
   nothing. Tabular figures still keep the numeric one aligned. */
.cr-stat b {
  display: block;
  font-family: var(--cr-font-heading);
  font-size: var(--cr-text-2xl);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.cr-stat span {
  display: block;
  color: var(--cr-text-muted);
  font-size: var(--cr-text-sm);
  margin-top: var(--cr-space-2);
  line-height: 1.5;
}
.cr-btn--block { width: 100%; box-sizing: border-box; }
.cr-stack > * + * { margin-top: var(--cr-space-4); }
/* A trust line under a button, not beside it: `.cr-eyebrow` is inline-flex, so
   without this it sat on the button's baseline and read as part of the CTA. */
.cr-trust { display: block; margin-top: var(--cr-space-4); }
