/*
  firmfact.com public pages — "counsel ledger" house style.

  Where marketdata.ai wears the warm-cream SLA-paper look (public_brand.css),
  Firmfact gets a cool porcelain surface, precise grotesque display type
  (Inter Display, self-hosted), hairline-ruled ledger tables with tabular
  numerals, deep navy primary actions, and the orange delta from the logo as
  both accent rule and ghost watermark.

  Everything is scoped to body.brand-firmfact so the marketdata brand — which
  shares these layouts and the legacy .btn / .form-* classes — is untouched.
  The homepage reuses md-* markup from public_brand.css; this file remaps the
  --md-* tokens and overrides display type, emphasis color, and primary actions.
*/

/* The "Inter Display" @font-face lives in inter.css (loaded on every page,
   public and authenticated), not here: the Firmfact logo wordmark is inlined
   app-wide and references the family, so declaring it only on public pages
   would render the in-app wordmark in fallback Inter. */

/* ---- Palette: cool porcelain (light) ---- */
body.brand-firmfact {
  --ff-bg: #f7f8f8;
  --ff-bg-2: #eff1f2;
  --ff-raise: #ffffff;
  --ff-ink: #14171c;
  --ff-ink-soft: #4a4f58;
  /* Muted copy must still clear WCAG AA small-text on every light surface:
     #6b7077 → 4.68:1 on --ff-bg, 4.98:1 on white (#7c8087 sat at 3.73). */
  --ff-ink-mute: #6b7077;
  --ff-line: rgba(20, 23, 28, 0.14);
  --ff-line-soft: rgba(20, 23, 28, 0.07);
  --ff-navy: #16233a;
  --ff-navy-soft: #24365a;
  --ff-orange: #ff8c00;
  /* Text-safe orange for copy on the light surfaces (raw #ff8c00 fails
     contrast): #a35500 → 5.1:1 on --ff-bg and 4.8:1 on the --ff-bg-2 bands;
     the previous #b45f00 sat just under AA at 4.31/4.05. */
  --ff-accent-text: #a35500;
  --ff-orange-hover: #ffb95c;
  --ff-on-navy: #fbfcfd;
  --ff-on-orange: #1a1104;
  --ff-display: "Inter Display", Inter, ui-sans-serif, system-ui, sans-serif;
  --ff-sans: Inter, ui-sans-serif, system-ui, sans-serif;

  /* Shared homepage markup uses --md-* tokens. Map them onto Firmfact so
     layout and copy stay identical while type and color stay this brand. */
  --md-paper: var(--ff-bg);
  --md-paper-2: var(--ff-bg-2);
  --md-paper-raise: var(--ff-raise);
  --md-ink: var(--ff-ink);
  --md-ink-soft: var(--ff-ink-soft);
  --md-ink-mute: var(--ff-ink-mute);
  --md-taupe: var(--ff-line);
  --md-line: var(--ff-line);
  --md-line-soft: var(--ff-line-soft);
  --md-teal: var(--ff-navy);
  --md-teal-deep: var(--ff-navy);
  --md-orange: var(--ff-orange);
  --md-serif-display: var(--ff-display);
  --md-serif-body: var(--ff-sans);
  --md-sans: var(--ff-sans);
}

/* ---- Palette: graphite (dark) ---- */
.dark body.brand-firmfact {
  --ff-bg: #101318;
  --ff-bg-2: #151920;
  --ff-raise: #171c24;
  --ff-ink: #e8eaee;
  --ff-ink-soft: #aab0ba;
  --ff-ink-mute: #7e848e;
  --ff-line: rgba(232, 234, 238, 0.16);
  --ff-line-soft: rgba(232, 234, 238, 0.08);
  --ff-navy: #22314e;
  --ff-navy-soft: #2c4066;
  --ff-orange: #ffa733;
  --ff-accent-text: #ffa733;
  /* TEXT accents in the dark theme. The light theme maps --md-teal to
     --ff-navy, which shared rules use to color inline links and small
     headings ("What is Firmfact?", quiet-links). Dark --ff-navy (#22314e) is
     a SURFACE tone — as text on graphite it disappears (1.4:1) — so remap
     the shared text token to a steel navy that reads (≥7:1 on --ff-bg).
     Buttons/chips are unaffected: their firmfact overrides use --ff-navy
     directly. */
  --md-teal: #8ea9dd;
  --md-teal-deep: #a9bde4;
}

/* ---- Page surface ---- */
/* Full-bleed bands and the agreement jump button need the viewport as the
   scroll container. Shared `body:not(.h-screen)` locks height and scrolls
   inside main, which (a) adds `main` padding gutters, (b) shrinks % widths
   by the scrollbar, and (c) leaves `back-to-top` listening to a window that
   never moves — so the agreement FAB stays at opacity-0. Same override as
   `public_brand.css` for Marketdata. Content shells keep their own max-w / px. */
body.brand-firmfact.static-page {
  background-color: var(--ff-bg);
  color: var(--ff-ink);
  font-family: var(--ff-sans);
  height: auto;
  min-height: 100vh;
  overflow-y: auto;
  /* Copy bands keep the Tailwind max-w-5xl measure; kept as a token for any
     rule that needs to quote it. The nav is deliberately NOT on this measure
     — it runs full-bleed (see the frosted header block below). */
  --ff-page-measure: 64rem;
}

body.brand-firmfact.static-page .min-h-screen {
  height: auto;
  min-height: 100vh;
}

body.brand-firmfact.static-page #main-content {
  padding: 0;
  overflow: visible;
}

/* Sticky frosted-glass header: full-width nav bar (logo hard left, actions
   hard right), translucent porcelain with backdrop blur so full-bleed bands
   slide beneath it — content stays legible through the glass. The solid-fill
   fallback covers browsers without backdrop-filter. */
body.brand-firmfact.static-page > .relative.z-30 > header {
  position: sticky;
  top: 0;
  z-index: 40;
  background-color: var(--ff-bg);
}

@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  body.brand-firmfact.static-page > .relative.z-30 > header {
    background-color: color-mix(in srgb, var(--ff-bg) 78%, transparent);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    backdrop-filter: saturate(180%) blur(20px);
  }
}

body.brand-firmfact.static-page > .relative.z-30 > header .top-nav {
  background-color: transparent;
  width: 100%;
  padding-inline: clamp(1rem, 3vw, 2.5rem);
}

body.brand-firmfact.static-page ::selection {
  background: rgba(255, 140, 0, 0.24);
}

/* ---- Ghost delta watermark (replaces the animated background) ---- */
body.brand-firmfact .css-delta,
body.brand-firmfact .bg-radial-gradient {
  display: none;
}

/* Opacity is set by luminance, not taste: a watermark needs roughly 4–6 L*
   of lightness difference against its ground to be subtle-but-visible
   (user report: invisible on a recent MacBook Pro at the old 0.06/0.05).
   Verified in sRGB — the worst case for visitors:
     light: #ff8c00 @ 0.13 over #f7f8f8 → blend #f8ead8, ΔL* ≈ 4.2
     dark:  #ffa733 @ 0.08 over #101318 → blend #232017, ΔL* ≈ 5.8
   Recompute both blends before changing color, opacity, or the page ground.

   Geometry: on desktop the WHOLE glyph sits above the fold, anchored to the
   lower left — a complete emblem, not a cropped texture, now that the hero is
   a centered stack. It must stay left of center: the product shot card is
   opaque and would swallow a centered mark. Sized against the small viewport
   (svh, vh fallback) so the browser chrome cannot push it under the fold; the
   path's own ~10% inner padding keeps the drawn triangle clear of the sticky
   nav. Phones keep the oversized crop below — a "whole" delta at 375px wide
   would shrink to a stamp. */
.ff-watermark {
  position: fixed;
  bottom: 3vh;
  bottom: 3svh;
  left: 2vw;
  width: min(88vh, 52vw);
  width: min(88svh, 52vw);
  height: min(88vh, 52vw);
  height: min(88svh, 52vw);
  color: var(--ff-orange);
  opacity: 0.13;
  pointer-events: none;
  z-index: 0;
}

.ff-watermark svg {
  width: 100%;
  height: 100%;
  display: block;
  fill: currentColor;
}

.dark .ff-watermark {
  opacity: 0.08;
}

@media (max-width: 768px) {
  .ff-watermark {
    bottom: -12vmax;
    left: -28vmax;
    width: 92vmax;
    height: 92vmax;
  }

  /* Keep auth pages lean on mobile — mirrors the marketdata LCP fix. */
  body.brand-firmfact.auth-page .ff-watermark {
    display: none;
  }
}

/* Shared homepage (.md-*) is painted with Firmfact type and color. Token
   remaps above cover most of the look; these overrides keep the grotesque
   display cut, orange emphasis, and navy primary actions. */
body.brand-firmfact .md-display {
  font-weight: 700;
  letter-spacing: -0.028em;
  line-height: 1.05;
}

body.brand-firmfact .md-display em,
body.brand-firmfact .md-accent-italic {
  font-style: normal;
  color: var(--ff-accent-text);
}

body.brand-firmfact .md-eyebrow,
body.brand-firmfact .md-section-label {
  color: var(--ff-accent-text);
  letter-spacing: 0.16em;
  font-weight: 650;
}

body.brand-firmfact .md-btn-primary {
  background: var(--ff-navy);
  color: var(--ff-on-navy);
}
body.brand-firmfact .md-btn-primary:hover {
  background: var(--ff-navy-soft);
  color: var(--ff-on-navy);
}
.dark body.brand-firmfact .md-btn-primary {
  background: var(--ff-orange);
  color: var(--ff-on-orange);
}
.dark body.brand-firmfact .md-btn-primary:hover {
  background: var(--ff-orange-hover);
}

body.brand-firmfact .md-btn:focus-visible {
  outline-color: var(--ff-accent-text);
}

/* Signup waiting-room / blocked-email dialogs. public_brand paints the
   overlay and panel; retint the backdrop to navy so it isn't leftover
   marketdata taupe on a porcelain page. */
body.brand-firmfact .md-modal-backdrop {
  background: rgba(22, 35, 58, 0.55);
}
.dark body.brand-firmfact .md-modal-backdrop {
  background: rgba(8, 11, 16, 0.72);
}

body.brand-firmfact [data-back-to-top-target="button"] {
  background-color: var(--ff-navy);
}
body.brand-firmfact [data-back-to-top-target="button"]:hover {
  background-color: var(--ff-navy-soft);
}
.dark body.brand-firmfact [data-back-to-top-target="button"] {
  background-color: var(--ff-orange);
  color: var(--ff-on-orange);
}
.dark body.brand-firmfact [data-back-to-top-target="button"]:hover {
  background-color: var(--ff-orange-hover);
}

/* ---- Layout chrome: header, nav, footer on porcelain ---- */
body.brand-firmfact header.flex-none {
  background-color: transparent;
}
body.brand-firmfact .top-nav {
  background-color: transparent;
  border-bottom-color: var(--ff-line);
}

/* Public wordmark only (in-app nav is 32px via body:not(.static-page)).
   Shared .top-nav forces svg { height: 24px }, so this has to outrank it.
   Do not use width:auto: the SVG has no width attribute, min-width:0, and the
   center links keep width:100%+nowrap — flex then crushes the mark to 0 and
   shoves Log In / Sign Up off the right edge. */
body.brand-firmfact.static-page .top-nav > .logo,
body.brand-firmfact.static-page .top-nav > .nav-user-controls {
  flex-shrink: 0;
}

body.brand-firmfact.static-page .top-nav > section.flex-1 {
  min-width: 0;
}

body.brand-firmfact.static-page .top-nav > section.flex-1 a {
  width: auto;
}

body.brand-firmfact.static-page .top-nav .logo a svg {
  height: 2rem;
  width: auto;
  aspect-ratio: 260 / 50;
  flex-shrink: 0;
  overflow: visible;
}

/* Phones: full wordmark (182px) + theme toggle + Log In + Sign Up (197px)
   overflow a 375px viewport and clipped the Sign Up button. Scale the mark
   and tighten the actions until everything fits with air to spare. */
@media (max-width: 480px) {
  body.brand-firmfact.static-page > .relative.z-30 > header .top-nav {
    padding-inline: 0.75rem;
  }

  body.brand-firmfact.static-page .top-nav .logo a svg {
    height: 1.625rem;
  }

  body.brand-firmfact.static-page .top-nav .nav-user-controls .btn {
    padding-inline: 0.7rem;
  }
}

/* Centered hero: copy narrow, shot wide. The shell keeps the shared 72rem
   Tailwind measure (wider than --ff-page-measure on purpose — the product
   shot is the page's one big object). min-width:0 keeps the bitmap from
   forcing layout. */
body.brand-firmfact.static-page .md-hero-visual,
body.brand-firmfact.static-page .md-frame {
  min-width: 0;
}

body.brand-firmfact.static-page .md-frame {
  width: 100%;
  max-width: 100%;
}

body.brand-firmfact.static-page .md-frame img,
body.brand-firmfact.static-page .md-frame video {
  min-width: 0;
  width: 100%;
  max-width: 100%;
  height: auto;
  object-fit: contain;
}

/* Glow behind the shot: the shared rule is teal (Marketdata). Retint to a
   faint brand orange so the porcelain stays cool and the warmth sits only
   behind the product. */
body.brand-firmfact.static-page .md-hero-glow {
  background: radial-gradient(ellipse at center, color-mix(in srgb, var(--ff-orange) 10%, transparent), transparent 65%);
}

.dark body.brand-firmfact.static-page .md-hero-glow {
  background: radial-gradient(ellipse at center, color-mix(in srgb, var(--ff-orange) 7%, transparent), transparent 65%);
}

/* ---- Homepage vertical rhythm (Apple-like: tight groups, loose bands) ----
   Shared markup uses py-16 / gap-5 / mt-10. Firmfact only: more air between
   sections and list rows, without changing Marketdata. */
body.brand-firmfact.static-page #main-content > .relative > section:not(.md-hero),
body.brand-firmfact.static-page #main-content > .relative > .md-band {
  padding-top: 5rem;
  padding-bottom: 5rem;
}

@media (min-width: 1024px) {
  body.brand-firmfact.static-page #main-content > .relative > section:not(.md-hero),
  body.brand-firmfact.static-page #main-content > .relative > .md-band {
    padding-top: 6.5rem;
    padding-bottom: 6.5rem;
  }

  /* Beat section:not(.md-hero) (same 1,4,2 otherwise keeps 6.5rem). 4.5rem
     sits between the old canyon and a jammed “why market data is hard”. */
  body.brand-firmfact.static-page #main-content > .relative > section.md-hero + section {
    padding-top: 4.5rem;
  }
}

body.brand-firmfact.static-page #main-content > .relative.flex {
  padding-bottom: 7rem;
}

body.brand-firmfact.static-page .md-section-label + .md-display {
  margin-top: 1.35rem;
}

body.brand-firmfact.static-page .md-rule {
  margin-top: 1.75rem;
  margin-bottom: 2.25rem;
}

/* Heading cluster stays tight; the rule's bottom margin is the only gap
   into the lede. Do not stack Tailwind mt-8 on top of that. */
body.brand-firmfact.static-page .md-rule + .md-lede {
  margin-top: 0;
}

body.brand-firmfact.static-page .md-lede {
  line-height: 1.7;
}

body.brand-firmfact.static-page .md-moments {
  margin-top: 3.5rem;
}

body.brand-firmfact.static-page .md-moment {
  padding-top: 2.5rem;
  padding-bottom: 2.5rem;
  gap: 1.5rem;
}

/* Shared chips tint --md-teal at 12%. Firmfact maps that token to navy, so
   dark mode becomes navy-on-navy and the label disappears. Solid pills. */
body.brand-firmfact.static-page .md-prepared-chip {
  color: var(--ff-navy);
  background: color-mix(in srgb, var(--ff-navy) 10%, var(--ff-raise));
  border-color: color-mix(in srgb, var(--ff-navy) 28%, var(--ff-line));
}

.dark body.brand-firmfact.static-page .md-prepared-chip {
  color: var(--ff-on-navy);
  background: var(--ff-navy-soft);
  border-color: color-mix(in srgb, var(--ff-ink) 22%, var(--ff-navy-soft));
}

body.brand-firmfact.static-page .md-closing-line {
  margin-top: 3rem;
}

body.brand-firmfact.static-page .md-proof-caption {
  margin-top: 1.35rem;
}

body.brand-firmfact.static-page .md-card {
  padding: 1.85rem 1.75rem;
}

body.brand-firmfact.static-page .md-card h3 {
  margin-bottom: 0.85rem;
}

body.brand-firmfact.static-page #main-content .grid.gap-4 {
  gap: 1.35rem;
}

body.brand-firmfact.static-page #main-content .grid.gap-5 {
  gap: 1.75rem;
}

@media (min-width: 1024px) {
  body.brand-firmfact.static-page [aria-labelledby="homepage-inbox-heading"] .grid {
    gap: 4.5rem;
  }
}

body.brand-firmfact.static-page .md-doc-panel {
  padding: 2.15rem 2rem;
}

body.brand-firmfact.static-page #main-content .mt-10 {
  margin-top: 3.25rem;
}

body.brand-firmfact.static-page #main-content .mt-12 {
  margin-top: 4rem;
}

body.brand-firmfact.static-page .md-band > section + section {
  padding-top: 5.5rem;
}

body.brand-firmfact.static-page .marketing-faq-card + .marketing-faq-card {
  margin-top: 0.85rem;
}

body.brand-firmfact.static-page .marketing-faq-trigger {
  padding: 1.75rem 1.65rem;
}

body.brand-firmfact.static-page .md-cta-panel {
  padding: 3.5rem 2.75rem;
}

body.brand-firmfact.static-page .md-cta-panel .mt-9 {
  margin-top: 2.75rem;
}

body.brand-firmfact .minimal-top-nav {
  background-color: transparent;
}
body.brand-firmfact footer {
  background-color: transparent;
  border-top-color: var(--ff-line);
}

/* Footer accents: the firmfact footer branch uses teal Tailwind kickers —
   swap them to the brand accent. Values are tokens, so dark mode comes free
   and this rule outranks the compiled dark: teal variant. */
body.brand-firmfact footer .text-teal-700 {
  color: var(--ff-accent-text);
}

/* ---- Recolor legacy .btn usages on public pages (nav Log In / Sign Up,
   the devise submit buttons) ---- */
/* accessibility.css paints every .btn-primary teal with !important from
   inside Tailwind's `utilities` cascade layer, and an important declaration
   in a layer outranks an important one outside any layer whatever its
   specificity. So this block joins the same layer, where specificity
   decides again. Without it the nav Sign Up and the sign-in Continue were
   teal-900 on the navy brand. */
@layer utilities {
body.brand-firmfact .btn-primary {
  background-color: var(--ff-navy) !important;
  color: var(--ff-on-navy) !important;
  border-color: transparent;
  border-radius: 5px;
}
body.brand-firmfact .btn-primary:hover,
body.brand-firmfact .btn-primary:active {
  background-color: var(--ff-navy-soft) !important;
  color: var(--ff-on-navy) !important;
}
.dark body.brand-firmfact .btn-primary {
  background-color: var(--ff-orange) !important;
  color: var(--ff-on-orange) !important;
}
.dark body.brand-firmfact .btn-primary:hover,
.dark body.brand-firmfact .btn-primary:active {
  background-color: var(--ff-orange-hover) !important;
  color: var(--ff-on-orange) !important;
}

/* Two states in accessibility.css outrank the rule above on specificity
   alone — `.btn-primary:focus:not(:focus-visible)` and
   `.btn-primary.btn-loading:disabled` are (0,3,0) against its (0,2,1) — so
   they kept painting teal-900 inside this same layer. A plain mouse click
   leaves the button focused without matching :focus-visible, so every
   clicked button turned teal the moment the pointer left it, and a
   submitting form button was teal for the whole request. Matching their
   states here puts them back on brand. Keyboard focus is untouched: it
   matches :focus-visible, keeps the resting fill, and keeps its ring. */
body.brand-firmfact .btn-primary:focus:not(:focus-visible),
body.brand-firmfact .btn-primary.btn-loading:disabled,
body.brand-firmfact .btn-primary.btn-loading:disabled:hover {
  background-color: var(--ff-navy) !important;
  color: var(--ff-on-navy) !important;
}
.dark body.brand-firmfact .btn-primary:focus:not(:focus-visible),
.dark body.brand-firmfact .btn-primary.btn-loading:disabled,
.dark body.brand-firmfact .btn-primary.btn-loading:disabled:hover {
  background-color: var(--ff-orange) !important;
  color: var(--ff-on-orange) !important;
}

/* A button keeps focus after the click, so without this the rule above would
   outrank the hover rule and a focused button would stop answering the
   pointer. */
body.brand-firmfact .btn-primary:focus:not(:focus-visible):hover {
  background-color: var(--ff-navy-soft) !important;
  color: var(--ff-on-navy) !important;
}
.dark body.brand-firmfact .btn-primary:focus:not(:focus-visible):hover {
  background-color: var(--ff-orange-hover) !important;
  color: var(--ff-on-orange) !important;
}
}
body.brand-firmfact .btn-white,
body.brand-firmfact .btn-secondary {
  background-color: transparent;
  color: var(--ff-ink);
  border-color: var(--ff-line);
  border-radius: 5px;
}
body.brand-firmfact .btn-white:hover,
body.brand-firmfact .btn-secondary:hover {
  background-color: var(--ff-raise);
  border-color: var(--ff-ink-soft);
}

/* Nav auth buttons: keep labels on one line; trim on small screens. */
body.brand-firmfact .nav-user-controls .btn {
  white-space: nowrap;
}
@media (max-width: 480px) {
  body.brand-firmfact .nav-user-controls .btn {
    min-height: 44px;
    padding: 7px 10px;
    font-size: 0.8125rem;
  }
}

/* Logo right-click press menu (brand_press_menu.js). */
.brand-menu {
  position: fixed;
  z-index: 9999;
  min-width: 200px;
  padding: 6px;
  border-radius: 12px;
  background: var(--ff-raise, #fff);
  color: var(--ff-ink, #14171c);
  border: 1px solid var(--ff-line, rgba(20, 23, 28, 0.14));
  box-shadow: 0 12px 32px rgba(20, 23, 28, 0.14);
  font: 14px/1.3 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
.brand-menu-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: 9px 12px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: inherit;
  cursor: pointer;
  font: inherit;
}
.brand-menu-item:hover {
  background: var(--ff-bg-2, rgba(20, 23, 28, 0.06));
}
.brand-menu-item:focus-visible {
  outline: 2px solid var(--ff-accent-text, #c45c26);
  outline-offset: -2px;
  background: var(--ff-bg-2, rgba(20, 23, 28, 0.06));
}
.dark .brand-menu {
  background: #1f2937;
  color: #f3f4f6;
  border-color: rgba(255, 255, 255, 0.12);
}
.dark .brand-menu-item:hover,
.dark .brand-menu-item:focus-visible {
  background: rgba(255, 255, 255, 0.08);
}

/* Theme-toggle focus ring on the porcelain surface. */
body.brand-firmfact [data-theme-toggle]:focus,
body.brand-firmfact [data-theme-toggle]:focus-visible {
  --tw-ring-color: var(--ff-accent-text);
  --tw-ring-offset-color: var(--ff-bg);
}

/* ---- Editorial prose (about, legal documents) ---- */
body.brand-firmfact .prose {
  color: var(--ff-ink-soft);
}
body.brand-firmfact .prose :where(h1, h2, h3, h4) {
  font-family: var(--ff-display);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ff-ink);
}
body.brand-firmfact .prose :where(strong) {
  color: var(--ff-ink);
}
body.brand-firmfact .prose :where(a) {
  color: var(--ff-accent-text);
}

/* ============================================================
   Forms, badges, modals — auth / error / minimal public pages.
   Legacy .form-* classes are repainted within brand scope so the
   devise views need no per-field edits. Loaded only on public
   firmfact pages; the authenticated app is untouched.
   ============================================================ */

body.brand-firmfact .form-control,
body.brand-firmfact .form-select {
  width: 100%;
  /* The app pins input.form-control / select.form-control to 38px, sized for
     its 14px/1.5 controls. These brand fields are 1rem/1.4 with 0.65rem
     padding and need ~45px, so the pin cropped their text — visibly on a
     select, which does not centre its value the way an input does. */
  height: auto;
  background-color: var(--ff-raise);
  border: 1px solid var(--ff-line);
  border-radius: 5px;
  color: var(--ff-ink);
  font-family: var(--ff-sans);
  font-size: 1rem;
  line-height: 1.4;
  padding: 0.65rem 0.85rem;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
body.brand-firmfact .form-control::placeholder {
  color: var(--ff-ink-mute);
}
body.brand-firmfact .form-control:focus,
body.brand-firmfact .form-select:focus {
  outline: none;
  border-color: var(--ff-accent-text);
  box-shadow: 0 0 0 3px rgba(255, 140, 0, 0.18);
}

body.brand-firmfact .form-label {
  display: block;
  font-family: var(--ff-sans);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--ff-ink-soft);
  margin-bottom: 0.4rem;
}
body.brand-firmfact .form-group {
  margin-bottom: 1.1rem;
}
body.brand-firmfact input[type="checkbox"],
body.brand-firmfact input[type="radio"] {
  accent-color: var(--ff-accent-text);
}

/* ---- Error pages: porcelain overlay (mirrors the marketdata approach) ---- */
body.brand-firmfact.error-page {
  background-color: var(--ff-bg);
}
body.brand-firmfact.error-page .bg-gray-50 {
  background-color: var(--ff-bg);
}
body.brand-firmfact.error-page .bg-white {
  background-color: var(--ff-raise);
}
body.brand-firmfact.error-page .border-gray-200,
body.brand-firmfact.error-page .border-gray-700 {
  border-color: var(--ff-line);
}
body.brand-firmfact.error-page .shadow {
  box-shadow: none;
}
body.brand-firmfact.error-page h2 {
  font-family: var(--ff-display);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ff-ink);
}
body.brand-firmfact.error-page .text-gray-900 {
  color: var(--ff-ink);
}
body.brand-firmfact.error-page .text-gray-600 {
  color: var(--ff-ink-soft);
}

/* ============================================================
   Pricing plan-builder (#plans) — porcelain repaint, PUBLIC only.
   Same scoping trick as public_brand.css: body.brand-firmfact only
   matches public pages, so /account/billing is untouched.
   ============================================================ */

body.brand-firmfact #plans h1,
body.brand-firmfact #plans h2,
body.brand-firmfact #plans h3 {
  font-family: var(--ff-display);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ff-ink);
}

body.brand-firmfact #plans .bg-white,
body.brand-firmfact #plans .bg-white\/85 {
  background-color: var(--ff-raise);
}
body.brand-firmfact #plans .bg-gray-50,
body.brand-firmfact #plans .bg-gray-100,
body.brand-firmfact #plans .bg-gray-200,
body.brand-firmfact #plans .bg-blue-50,
body.brand-firmfact #plans .bg-blue-50\/60 {
  background-color: var(--ff-bg-2);
}

body.brand-firmfact #plans .shadow-md,
body.brand-firmfact #plans .shadow-sm {
  box-shadow: none;
}

body.brand-firmfact #plans .border-gray-200,
body.brand-firmfact #plans .border-gray-700,
body.brand-firmfact #plans .border-blue-100,
body.brand-firmfact #plans .border-blue-200,
body.brand-firmfact #plans .border-blue-800 {
  border-color: var(--ff-line);
}
body.brand-firmfact #plans .border-blue-500 {
  border-color: var(--ff-orange);
}

body.brand-firmfact #plans .text-gray-900,
body.brand-firmfact #plans .text-gray-800 {
  color: var(--ff-ink);
}
body.brand-firmfact #plans .text-gray-600,
body.brand-firmfact #plans .text-gray-500 {
  color: var(--ff-ink-soft);
}
body.brand-firmfact #plans .text-gray-400 {
  color: var(--ff-ink-mute);
}

body.brand-firmfact #plans .text-green-500,
body.brand-firmfact #plans .text-blue-500,
body.brand-firmfact #plans .text-blue-600,
body.brand-firmfact #plans .text-blue-400 {
  color: var(--ff-accent-text);
}
body.brand-firmfact #plans .bg-blue-600,
body.brand-firmfact #plans .bg-green-600 {
  background-color: var(--ff-navy);
}
.dark body.brand-firmfact #plans .bg-blue-600,
.dark body.brand-firmfact #plans .bg-green-600 {
  background-color: var(--ff-navy-soft);
}

/* Tier avatar gradients → flat fills deep enough for white labels in both
   themes. Keyed off _plan_selection.html.erb's tier_avatar_classes — keep in
   sync if those classes change. */
body.brand-firmfact #plans .bg-linear-to-br {
  background-image: none;
  background-color: #16233a;
}
body.brand-firmfact #plans .bg-linear-to-br.from-amber-500 {
  background-color: #b45309;
}
body.brand-firmfact #plans .bg-linear-to-br.from-blue-600 {
  background-color: #1d4ed8;
}
body.brand-firmfact #plans .bg-linear-to-br.from-emerald-500 {
  background-color: #0f766e;
}
body.brand-firmfact #plans .bg-linear-to-br.from-slate-400 {
  background-color: #475569;
}
body.brand-firmfact #plans .bg-linear-to-r {
  background-image: none;
  background-color: var(--ff-bg-2);
}

/* Save / discount badges → muted orange */
body.brand-firmfact #plans .bg-green-100 {
  background-color: rgba(255, 140, 0, 0.12);
}
body.brand-firmfact #plans .text-green-800,
body.brand-firmfact #plans .text-green-600 {
  color: var(--ff-accent-text);
}

body.brand-firmfact #plans .ring-blue-500 {
  --tw-ring-color: var(--ff-orange);
}

body.brand-firmfact #plans .duration-tab {
  min-height: 44px;
}

body.brand-firmfact #plans .text-amber-700,
body.brand-firmfact #plans .text-amber-600,
body.brand-firmfact #plans .text-amber-300,
body.brand-firmfact #plans .text-amber-400 {
  color: var(--ff-accent-text);
}

/* ---- Public feedback form (footer disclosure) ---- */
body.brand-firmfact .public-feedback-toggle {
  background: var(--ff-navy);
  color: #fff;
  font-family: var(--ff-sans);
}
body.brand-firmfact .public-feedback-toggle:hover {
  background: var(--ff-navy-soft);
  color: #fff;
}
body.brand-firmfact .public-feedback-panel {
  background: var(--ff-raise);
  border: 1px solid var(--ff-line);
  box-shadow: none;
}
body.brand-firmfact .public-feedback-intro,
body.brand-firmfact .public-feedback-label {
  color: var(--ff-ink-soft);
}
body.brand-firmfact .public-feedback-input {
  background: var(--ff-bg);
  border-color: var(--ff-line);
  color: var(--ff-ink);
}
body.brand-firmfact .public-feedback-input:focus {
  border-color: var(--ff-accent-text);
}
body.brand-firmfact .public-feedback-submit {
  background: var(--ff-navy);
}
body.brand-firmfact .public-feedback-submit:hover {
  background: var(--ff-navy-soft);
}

/* Sign-up value panel: the headline cycles three F-phrases above the brand
   line ("Free forever. / Fast forward. / Facts first." then "Firmfact.").
   Pure CSS. The phrases stack in one grid cell so the line reserves the
   width of the longest phrase and the panel never reflows; the cell clips
   the phrase sliding out. Reduced motion pins the first phrase. */
body.brand-firmfact.auth-page .ff-rotor {
  display: inline-grid;
  overflow: hidden;
  vertical-align: bottom;
}

body.brand-firmfact.auth-page .ff-rotor > span {
  grid-area: 1 / 1;
  opacity: 0;
  transform: translateY(0.6em);
  animation: ff-rotor 9s cubic-bezier(0.2, 0.7, 0.2, 1) infinite;
}

body.brand-firmfact.auth-page .ff-rotor > span:nth-child(2) {
  animation-delay: 3s;
}

body.brand-firmfact.auth-page .ff-rotor > span:nth-child(3) {
  animation-delay: 6s;
}

@keyframes ff-rotor {
  0% { opacity: 0; transform: translateY(0.6em); }
  7%, 27% { opacity: 1; transform: translateY(0); }
  34%, 100% { opacity: 0; transform: translateY(-0.6em); }
}

@media (prefers-reduced-motion: reduce) {
  body.brand-firmfact.auth-page .ff-rotor > span {
    animation: none;
  }

  body.brand-firmfact.auth-page .ff-rotor > span:first-child {
    opacity: 1;
    transform: none;
  }
}
