/*
 * @bsuite/theme — utility classes
 *
 * Pure CSS (no Tailwind @apply) so this file is safe to import from any
 * consumer on Tailwind v4 or later.
 */

/* ===== Glow effects (oklch with alpha scaled by glow-strength) ===== */
.glow-electric-blue {
  box-shadow: 0 0 20px oklch(0.546 0.215 262.9 / var(--glow-strength));
}
.glow-electric-cyan {
  box-shadow: 0 0 20px oklch(0.769 0.132 191.7 / var(--glow-strength));
}
.glow-electric-indigo {
  box-shadow: 0 0 20px oklch(0.511 0.23 277 / var(--glow-strength));
}
.glow-electric-purple {
  box-shadow: 0 0 20px oklch(0.568 0.202 283.1 / var(--glow-strength));
}
.glow-electric-pink {
  box-shadow: 0 0 20px oklch(0.656 0.212 354.3 / var(--glow-strength));
}
.glow-electric-coral {
  box-shadow: 0 0 20px oklch(0.669 0.219 20.9 / var(--glow-strength));
}
.glow-electric-magenta {
  box-shadow: 0 0 20px oklch(0.742 0.167 359.5 / var(--glow-strength));
}

/* ===== Neon text shadows ===== */
.neon-text-cyan {
  text-shadow: 0 0 10px oklch(0.769 0.132 191.7 / 0.5),
               0 0 20px oklch(0.769 0.132 191.7 / 0.3);
}
.neon-text-electric {
  text-shadow: 0 0 10px oklch(0.546 0.215 262.9 / 0.5),
               0 0 20px oklch(0.546 0.215 262.9 / 0.3);
}

/* ===== Smooth theme transition ===== */
.transition-theme {
  transition:
    background-color 300ms ease,
    border-color 300ms ease,
    color 300ms ease,
    box-shadow 300ms ease;
}

/* ============================================================
   CANONICAL ACCENT GRADIENT — W3 §3.1
   Exactly ONE gradient exists suite-wide: --role-primary -> --role-accent
   (Electric Blue -> Cyan by default; follows tenant BrandingProvider
   overrides automatically via the var() chain). Marketing/pre-auth hero
   surfaces ONLY — never functional text, labels, or body copy. Apply to
   a decorative element (underline, badge, background swatch) or to text
   via `background-clip: text` at the call site — this utility only
   supplies the gradient itself.
   ============================================================ */
.bsuite-accent-gradient {
  background-image: var(--gradient-accent);
}

/* ============================================================
   HERO GRID — W3 §3.3 grid/dot doctrine
   Public/pre-auth marketing hero bands ONLY. Localised to the hero
   wrapper (which must be `position: relative`); never full-viewport,
   never behind authenticated content. Mutually exclusive with the DOT
   pattern (packages/ui DotPattern), which is authenticated-shell-only.
   Consumed via the <HeroGrid> component in @bsuite/ui (packages/ui/src/
   hero-grid.tsx) — do not hand-roll this pattern; the grid/dot lint rule
   (@bsuite/dry-lint no-grid-dot-doctrine-violation) flags duplicates.
   Lifted verbatim from braden's `.platform-hero-grid`
   (braden/src/index.css) so the corporate and D2C marketing surfaces
   share one visual language for this specific device.
   ============================================================ */
/* Grid lines are hue-matched to the surface, never pure black/white — the
   contract bans both endpoints in every role, alpha forms included. Light
   mode stays neutral and quiet; dark mode takes a faint accent cast, which
   is where the cyber register lives. 32px = the pre-auth marketing tile. */
.bsuite-hero-grid {
  position: absolute;
  inset: 0;
  --grid-line: oklch(0.40 0.030 258 / 0.07);
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 32px 32px;
}
.dark .bsuite-hero-grid {
  --grid-line: oklch(0.82 0.020 262 / 0.055);
}

/* ===== prefers-reduced-motion — cap animation duration ===== */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ============================================================
   GRADIENT TEXT — the display-heading treatment
   ============================================================
   Operator ruling 2026-08-04: a page TITLE carries the accent gradient, on
   authenticated surfaces too. That widens the `.bsuite-accent-gradient` note
   above, which restricted the gradient to marketing/pre-auth heroes — the ban
   it was really protecting is on FUNCTIONAL text (labels, body copy, values,
   anything you read to make a decision), and a page title is none of those.

   Uses --gradient-heading, NOT --gradient-accent. The raw accent gradient ends
   in cyan at 1.76:1 on the light background, which would leave half the word
   unreadable; --gradient-heading is built from the AA-verified *-text variants
   and is correct in both modes. See the token for the measurements.

   background-clip: text requires `color: transparent`, so a gradient that fails
   to resolve produces INVISIBLE text rather than an ugly one. Both stops
   therefore come from tokens the package itself defines. */
.text-gradient-accent {
  /* TENANT FIRST, THEME DEFAULT SECOND.

     --heading-gradient is what the branding resolver (useBranding.ts) writes
     from `platform_branding.heading_gradient` / `tenant_branding.heading_gradient`.
     --gradient-heading is this package's own default. Reading ONLY the default
     meant a tenant's configured heading gradient could never reach this
     utility, so propagating it estate-wide would have delivered consistent
     defaults AND silently disabled white-label headings — a var with no reader
     reads as working, because the default looks right.

     PROVABLY A NO-OP TODAY: measured on production 2026-08-25, ZERO rows in
     either branding table have heading_gradient set, so the first var is unset
     and the fallback resolves to exactly today's value. Zero visual change now;
     white-label works the moment anyone sets one. */
  background-image: var(--heading-gradient, var(--gradient-heading));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* SHRINK-WRAP, and this is the whole reason the effect is visible.
     background-clip: text paints the gradient across the ELEMENT BOX, not the
     glyphs. A block-level h1 spans its container, so a short word samples only
     the first ~15% of the gradient and the far stop never reaches the screen —
     it renders as a flat colour, which is indistinguishable from the bug this
     replaces. fit-content makes the box hug the text so the gradient spans the
     letters. */
  width: fit-content;
  /* A gradient heading must still be selectable and searchable. background-clip
     keeps the real glyphs, so text selection, find-in-page and screen readers
     are unaffected — do not reach for an SVG or an image here. */
}

/* Forced-colours mode drops background-image entirely, which would leave
   transparent glyphs on screen. Hand the text back to the system palette. */
@media (forced-colors: active) {
  .text-gradient-accent { background-image: none; color: CanvasText; }
}

/* ── NAV / SWITCHER GRADIENT UNDERLINE ───────────────────────────────────
   TH-6. Promoted from crm7/src/index.css, 2026-08-17.

   The operator asked for the nav gradient underline in every app. It was
   unimplementable anywhere but crm7, because the treatment existed only in
   crm7's own stylesheet — 3 files in one app (the two declarations here plus
   two call sites), and ZERO occurrences in this package or in the other five
   apps. A request that needs a copy-paste to satisfy is a packaging defect,
   not a feature request, and copying it would have produced six declarations
   drifting apart the way `--bg-shell-elevated` did.

   It paints from --gradient-accent, which this package already owns, so
   nothing app-specific came with it.

   TWO FORMS, ONE PAINT SOURCE — that pairing is the point. Keeping them
   adjacent is what makes "the switcher and the active nav item match" a fact
   about this file rather than two declarations someone has to remember to
   keep in step:

     `-span`   the caller already renders its own absolutely-positioned
               element for the rule (crm7's tenant switcher does).
     `::after` the caller does not, so the rule is generated for it (the
               navigation items). REQUIRES `position: relative` on the host —
               without it the rule anchors to the nearest positioned ancestor
               and lands somewhere else on the page.

   The `-span` form carries no geometry on purpose: the caller owns its own
   inset/height/opacity, and crm7's switcher sets `opacity-70` with a
   `group-hover:opacity-100` transition. Only the paint is shared. */
.bsuite-gradient-underline-span {
  background: var(--gradient-accent);
}

.bsuite-gradient-underline::after {
  content: '';
  position: absolute;
  inset-inline: 0.5rem;
  bottom: 0.125rem;
  height: 0.125rem;
  border-radius: 9999px;
  background: var(--gradient-accent);
  opacity: 0.7;
  pointer-events: none;
}
