/* =============================================================
   HONESTLI DESIGN SYSTEM
   A self-contained CSS layer to replace Bootstrap 5.3.
   Lives at: wwwroot/honestli.css (alongside showcase.html).
   Reference once in App.razor (or _Host.cshtml) — no JS dependency.

   Layers (top → bottom):
     1. TOKENS       — design primitives (colors, type, space)
     2. BASE         — html/body, focus rings, scrollbars
     3. LAYOUT       — container, grid, stack, row
     4. UTILITIES    — text, spacing, decoration helpers
     5. COMPONENTS   — buttons, cards, badges, chips, inputs, …
     6. ANIMATIONS   — keyframes used across the system

   Convention: every class starts with `hl-`.
   No bare element selectors except in BASE.
   ============================================================= */

/* -------------------------------------------------------------
   1. TOKENS
   ------------------------------------------------------------- */
:root {
  /* Surfaces */
  --hl-bg:              #0D182A;
  --hl-bg-elev:         #12213A;
  --hl-bg-elev-2:       #1a2d4d;
  --hl-bg-overlay:      rgba(13, 24, 42, 0.72);

  /* Borders */
  --hl-border:          rgba(255, 255, 255, 0.06);
  --hl-border-strong:   rgba(255, 255, 255, 0.10);
  --hl-border-focus:    rgba(249, 115, 22, 0.55);

  /* Text */
  --hl-text:            #ffffff;
  --hl-text-2:          #d1d5db;
  --hl-text-muted:      #9ca3af;
  --hl-text-faint:      #6b7280;
  --hl-text-dim:        #3a4866;

  /* Brand & status */
  --hl-accent:          #F97316;  /* Pro */
  --hl-accent-soft:     rgba(249, 115, 22, 0.13);
  --hl-accent-glow:     rgba(249, 115, 22, 0.40);

  /* The second brand colour, used opposite the orange in headline accents,
     gradients and glows. Distinct from --hl-info (#60A5FA) and --hl-violet
     (#A78BFA), which are *plan* colours (Basic / Max) and carry meaning.
     This one is decorative — and only ~4.2:1 against the page background, so
     it belongs on display type (the hero headline accent), not on 11px labels.
     Where a blue eyebrow or chip is wanted, --hl-info reads at ~7:1.
     NOTE: #546EFA is hard-coded ~430 times across the scoped stylesheets and
     #FF7F27 (a near-duplicate of --hl-accent) ~110 more. This token exists so
     the blocks #391 touched could stop adding to that; the rest is a separate
     sweep — see the follow-up noted on that issue. */
  --hl-accent-blue:      #546EFA;

  --hl-info:            #60A5FA;  /* Basic */
  --hl-info-soft:       rgba(96, 165, 250, 0.13);

  --hl-violet:          #A78BFA;  /* Max */
  --hl-violet-soft:     rgba(167, 139, 250, 0.13);

  --hl-success:         #4ade80;
  --hl-success-soft:    rgba(74, 222, 128, 0.13);
  --hl-warning:         #fbbf24;
  --hl-warning-soft:    rgba(251, 191, 36, 0.13);
  --hl-danger:          #ef4444;
  --hl-danger-soft:     rgba(239, 68, 68, 0.13);

  /* Typography */
  --hl-font-sans:       'Lexend', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --hl-font-mono:       ui-monospace, 'SF Mono', Menlo, 'Cascadia Code', monospace;

  --hl-fs-xs:           11px;
  --hl-fs-sm:           12.5px;
  --hl-fs-md:           14px;
  --hl-fs-lg:           17px;
  --hl-fs-xl:           22px;
  --hl-fs-2xl:          32px;
  --hl-fs-3xl:          clamp(32px, 4.4vw, 52px);

  --hl-lh-tight:        1.1;
  --hl-lh-snug:         1.35;
  --hl-lh-normal:       1.5;
  --hl-lh-relaxed:      1.6;

  /* Spacing scale — 4px base */
  --hl-sp-0:            0;
  --hl-sp-1:            4px;
  --hl-sp-2:            8px;
  --hl-sp-3:            12px;
  --hl-sp-4:            16px;
  --hl-sp-5:            20px;
  --hl-sp-6:            24px;
  --hl-sp-7:            28px;
  --hl-sp-8:            32px;
  --hl-sp-10:           40px;
  --hl-sp-12:           48px;
  --hl-sp-16:           64px;

  /* Radii */
  --hl-r-sm:            6px;
  --hl-r-md:            10px;
  --hl-r-lg:            14px;
  --hl-r-xl:            20px;
  --hl-r-pill:          999px;

  /* Shadows */
  --hl-shadow-card:     0 10px 30px -16px rgba(0, 0, 0, 0.5);
  --hl-shadow-pop:      0 24px 48px -20px rgba(0, 0, 0, 0.6);
  --hl-shadow-inset:    inset 0 1px 0 rgba(255, 255, 255, 0.04);
  --hl-ring:            0 0 0 3px rgba(249, 115, 22, 0.25);

  /* Motion */
  --hl-ease:            cubic-bezier(0.4, 0, 0.2, 1);
  --hl-dur-fast:        150ms;
  --hl-dur-base:        250ms;
  --hl-dur-slow:        450ms;

  /* Layout */
  --hl-container:       1240px;
}

/* -------------------------------------------------------------
   2. BASE
   ------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--hl-bg);
  color: var(--hl-text-2);
  font-family: var(--hl-font-sans);
  line-height: var(--hl-lh-normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Base text size lives on <body>, NOT <html>. Setting font-size on the root
   element redefines what 1rem means for the whole document — and because this
   sheet loads before Bootstrap (which never resets html's size), a 14px root
   silently shrank every Bootstrap rem-based size to 87.5% (the "too small /
   inconsistent" report). Keep the root at the 16px browser default so rem-based
   (Bootstrap) typography is unaffected; hl- components use fixed px / tokens and
   don't depend on this. */
body { font-size: var(--hl-fs-md); }

body { min-height: 100vh; }

h1, h2, h3, h4, h5, h6 {
  margin: 0;
  color: var(--hl-text);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: var(--hl-lh-tight);
}

p { margin: 0; }
a { color: var(--hl-info); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }

button { font-family: inherit; }

::selection {
  background: var(--hl-accent);
  color: #fff;
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: var(--hl-r-pill); }
::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.14); }
::-webkit-scrollbar-track { background: transparent; }

:focus-visible {
  outline: 2px solid var(--hl-accent);
  outline-offset: 2px;
  border-radius: var(--hl-r-sm);
}

img, svg { display: block; max-width: 100%; }

/* -------------------------------------------------------------
   3. LAYOUT
   ------------------------------------------------------------- */
.hl-container {
  width: 100%;
  max-width: var(--hl-container);
  margin: 0 auto;
  padding: 0 var(--hl-sp-6);
}
.hl-container--narrow { max-width: 720px; }
.hl-container--medium { max-width: 920px; }
.hl-container--wide   { max-width: 1080px; }

.hl-stack { display: flex; flex-direction: column; }
.hl-row   { display: flex; flex-direction: row; align-items: center; }
.hl-row--top    { align-items: flex-start; }
.hl-row--baseline { align-items: baseline; }
.hl-row--between { justify-content: space-between; }
.hl-row--center { justify-content: center; }
.hl-row--end    { justify-content: flex-end; }
.hl-row--wrap   { flex-wrap: wrap; }

.hl-grid    { display: grid; }
.hl-grid-2  { grid-template-columns: 1fr 1fr; }
.hl-grid-3  { grid-template-columns: repeat(3, 1fr); }
.hl-grid-4  { grid-template-columns: repeat(4, 1fr); }
.hl-grid-billing {
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
}

@media (max-width: 860px) {
  .hl-grid-2, .hl-grid-3, .hl-grid-4, .hl-grid-billing { grid-template-columns: 1fr; }
}

/* Gap utilities — work on flex AND grid */
.hl-gap-1  { gap: var(--hl-sp-1); }
.hl-gap-2  { gap: var(--hl-sp-2); }
.hl-gap-3  { gap: var(--hl-sp-3); }
.hl-gap-4  { gap: var(--hl-sp-4); }
.hl-gap-5  { gap: var(--hl-sp-5); }
.hl-gap-6  { gap: var(--hl-sp-6); }
.hl-gap-8  { gap: var(--hl-sp-8); }
.hl-gap-10 { gap: var(--hl-sp-10); }

.hl-flex-1   { flex: 1; min-width: 0; }
.hl-flex-0   { flex: 0 0 auto; }

/* -------------------------------------------------------------
   4. UTILITIES
   ------------------------------------------------------------- */
.hl-text-center { text-align: center; }
.hl-text-right  { text-align: right; }
.hl-text-left   { text-align: left; }

.hl-text-primary { color: var(--hl-text); }
.hl-text-2       { color: var(--hl-text-2); }
.hl-text-muted   { color: var(--hl-text-muted); }
.hl-text-faint   { color: var(--hl-text-faint); }

.hl-text-accent  { color: var(--hl-accent); }
.hl-text-info    { color: var(--hl-info); }
.hl-text-violet  { color: var(--hl-violet); }
.hl-text-success { color: var(--hl-success); }
.hl-text-danger  { color: var(--hl-danger); }

.hl-fs-xs  { font-size: var(--hl-fs-xs); }
.hl-fs-sm  { font-size: var(--hl-fs-sm); }
.hl-fs-md  { font-size: var(--hl-fs-md); }
.hl-fs-lg  { font-size: var(--hl-fs-lg); }
.hl-fs-xl  { font-size: var(--hl-fs-xl); }
.hl-fs-2xl { font-size: var(--hl-fs-2xl); }
.hl-fs-3xl { font-size: var(--hl-fs-3xl); }

.hl-fw-400 { font-weight: 400; }
.hl-fw-500 { font-weight: 500; }
.hl-fw-600 { font-weight: 600; }
.hl-fw-700 { font-weight: 700; }

.hl-tabular { font-variant-numeric: tabular-nums; }
.hl-mono    { font-family: var(--hl-font-mono); }

.hl-truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Eyebrow label — small caps section header.
   Block by default so it stacks above whatever follows in centered hero
   blocks. Inside .hl-row / flex containers it just becomes a flex item
   and aligns normally. Use .hl-eyebrow--inline for runs of inline text.

   Tracking is 0.14em, not the 0.10em this rule shipped with. #391 swept the
   nineteen one-off eyebrows and found thirteen of them, across ten files,
   independently at 0.14em. The six dissenters were 0.16 twice in GetStory,
   0.12 in Error and PaymentConfirmation, 0.10 in Upgrade and 0.08 in
   ShareModal — and five of the six are looser than 0.10em, not tighter, so
   the pages were the signal and the token was the outlier. Widening also
   suits the size: 11px uppercase needs more tracking than 0.10em gives it.
   This moves the WizardShell and PageHeader eyebrows too, which is the point
   of them sharing a class.

   Size/weight stayed at 11px/700 (--hl-fs-xs), which is what most of the
   one-offs already used; Home and Stories were the two at 12px/600. */
.hl-eyebrow {
  display: block;
  font-size: var(--hl-fs-xs);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--hl-text-muted);
}
.hl-eyebrow--inline { display: inline-block; }
/* Bare row — no chip. For eyebrows that carry a dot or rule alongside the
   text but shouldn't look like a pill (GetStory's, Upgrade's plan cards). */
.hl-eyebrow--row {
  display: inline-flex;
  align-items: center;
  gap: var(--hl-sp-2);
}
.hl-eyebrow--accent  { color: var(--hl-accent); }
.hl-eyebrow--info    { color: var(--hl-info); }
.hl-eyebrow--violet  { color: var(--hl-violet); }
.hl-eyebrow--success { color: var(--hl-success); }
.hl-eyebrow--danger  { color: var(--hl-danger); }
/* One step quieter than the default muted — the unemphasised state of a
   two-state eyebrow. Upgrade's plan cards use it for the tiers that aren't
   the recommended one, which flips to --accent. */
.hl-eyebrow--faint   { color: var(--hl-text-faint); }

/* Pill — the eyebrow as a rounded chip rather than bare text. Four marketing
   pages had this hand-rolled at identical values (About, Contact, Privacy in
   orange; How it works in blue).

   Background and border derive from currentColor via color-mix, so one rule
   serves every colour modifier above and adding a fifth needs no work here.
   This is the sheet's first use of color-mix — Baseline since 2023, and the
   whole system is dark-theme-only with no IE/legacy target. */
.hl-eyebrow--pill {
  display: inline-flex;
  align-items: center;
  gap: var(--hl-sp-2);
  padding: 5px var(--hl-sp-3);
  border-radius: var(--hl-r-pill);
  background: color-mix(in srgb, currentColor 14%, transparent);
}
/* Adds the hairline outline the two status chips (Error, PaymentConfirmation)
   carried and the plain marketing pills did not. Kept as a separate modifier
   rather than folded into --pill so adopting the pill doesn't silently put a
   border on pages that never had one. */
.hl-eyebrow--outlined {
  border: 1px solid color-mix(in srgb, currentColor 28%, transparent);
}
/* Status dot. currentColor means it always matches its eyebrow's colour
   modifier — that was the only thing separating the orange and green copies
   of this in Error.razor.css and PaymentConfirmation.razor.css. */
.hl-eyebrow__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  flex-shrink: 0;
  background: currentColor;
  box-shadow: 0 0 8px color-mix(in srgb, currentColor 85%, transparent);
}
.hl-eyebrow__dot--pulse {
  animation: hl-dot-pulse 2.2s ease-in-out infinite;
}
/* Thin rule used instead of a dot — GetStory sets its eyebrow off with one. */
.hl-eyebrow__rule {
  width: 22px;
  height: 1px;
  flex-shrink: 0;
  background: currentColor;
  opacity: 0.6;
}

/* Decorative background glow — position with inline style */
.hl-glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(80px);
  pointer-events: none;
  z-index: 0;
}
.hl-glow--orange { background: radial-gradient(circle, rgba(249,115,22,0.18) 0%, transparent 70%); }
.hl-glow--violet { background: radial-gradient(circle, rgba(167,139,250,0.20) 0%, transparent 70%); }
.hl-glow--info   { background: radial-gradient(circle, rgba(96,165,250,0.18) 0%, transparent 70%); }

/* Divider */
.hl-divider {
  height: 1px;
  background: var(--hl-border);
  border: 0;
  margin: 0;
}
.hl-divider--dashed { background: transparent; border-top: 1px dashed var(--hl-border-strong); }

/* Margin helpers — keep these small. Prefer gap. */
.hl-mt-1 { margin-top: var(--hl-sp-1); }
.hl-mt-2 { margin-top: var(--hl-sp-2); }
.hl-mt-3 { margin-top: var(--hl-sp-3); }
.hl-mt-4 { margin-top: var(--hl-sp-4); }
.hl-mt-6 { margin-top: var(--hl-sp-6); }
.hl-mt-8 { margin-top: var(--hl-sp-8); }
.hl-mt-10 { margin-top: var(--hl-sp-10); }

.hl-position-relative { position: relative; }
.hl-overflow-hidden   { overflow: hidden; }

/* -------------------------------------------------------------
   5. COMPONENTS
   ------------------------------------------------------------- */

/* ── 5.1 BUTTON ──────────────────────────────────── */
.hl-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--hl-sp-2);
  padding: 10px var(--hl-sp-4);
  border-radius: var(--hl-r-md);
  border: 1px solid transparent;
  background: transparent;
  color: inherit;
  font-family: var(--hl-font-sans);
  font-size: var(--hl-fs-md);
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
  /* Bootstrap loads after this file and re-adds `a { text-decoration: underline }`,
     so <a class="hl-btn"> renders underlined unless the class declares it here.
     Class (0,1,0) beats the element selector (0,0,1) regardless of order. */
  text-decoration: none;
  transition: background var(--hl-dur-fast) var(--hl-ease),
              border-color var(--hl-dur-fast) var(--hl-ease),
              color var(--hl-dur-fast) var(--hl-ease),
              transform var(--hl-dur-fast) var(--hl-ease),
              filter var(--hl-dur-fast) var(--hl-ease);
  white-space: nowrap;
  user-select: none;
}
.hl-btn:disabled, .hl-btn[aria-disabled="true"] {
  opacity: 0.5; cursor: not-allowed;
}
/* `a:hover` (0,1,1) outranks `.hl-btn` (0,1,0), so the base rule above isn't
   enough on its own — an <a class="hl-btn"> would underline on hover. */
.hl-btn:hover { text-decoration: none; }
.hl-btn:focus-visible { box-shadow: var(--hl-ring); outline: none; }

/* Variants */
.hl-btn--primary {
  background: var(--hl-accent);
  color: #fff;
  box-shadow: 0 6px 18px -8px var(--hl-accent-glow);
}
.hl-btn--primary:hover:not(:disabled) { filter: brightness(1.08); transform: translateY(-1px); }
.hl-btn--primary:active { transform: translateY(0); }

.hl-btn--hero {
  background: linear-gradient(135deg, var(--hl-accent) 0%, #fb923c 100%);
  color: #fff;
  box-shadow: 0 12px 28px -10px var(--hl-accent-glow);
}
.hl-btn--hero:hover:not(:disabled) { filter: brightness(1.06); transform: translateY(-1px); }

.hl-btn--secondary {
  background: var(--hl-bg-elev-2);
  color: var(--hl-text);
  border-color: var(--hl-border-strong);
}
.hl-btn--secondary:hover:not(:disabled) { background: #213657; }

.hl-btn--outline {
  background: transparent;
  color: var(--hl-text-2);
  border-color: var(--hl-border-strong);
}
.hl-btn--outline:hover:not(:disabled) {
  background: rgba(255,255,255,0.04);
  color: var(--hl-text);
  border-color: rgba(255,255,255,0.16);
}

.hl-btn--ghost {
  background: transparent;
  color: var(--hl-text-muted);
}
.hl-btn--ghost:hover:not(:disabled) {
  background: rgba(255,255,255,0.05);
  color: var(--hl-text);
}

.hl-btn--danger {
  background: var(--hl-danger);
  color: #fff;
}
.hl-btn--danger:hover:not(:disabled) { filter: brightness(1.08); }

/* Sizes */
.hl-btn--sm { padding: 7px var(--hl-sp-3); font-size: var(--hl-fs-sm); border-radius: var(--hl-r-sm); }
.hl-btn--md { padding: 10px var(--hl-sp-4); font-size: var(--hl-fs-md); }
.hl-btn--lg { padding: 14px var(--hl-sp-6); font-size: var(--hl-fs-lg); }

.hl-btn--block { width: 100%; }

/* Icon-only — a square button whose whole content is one icon. Use it for the
   trash affordance on a card in a list, where a "Delete" label would crowd the
   row. Combine with a variant as usual: `.hl-btn.hl-btn--danger.hl-btn--icon`.

   The width/height are the text buttons' heights spelled out (font-size +
   padding + border, box-sizing: border-box), so an icon button sits flush
   against a text button of the same size instead of coming out narrow and
   rectangular the way a bare <i> inside a padded .hl-btn does.

   These buttons have no text, so `aria-label` is REQUIRED — `title` alone is
   not an accessible name for every assistive technology. */
.hl-btn--icon {
  gap: 0;
  padding: 10px;
  flex-shrink: 0;
  width: calc(var(--hl-fs-md) + 22px);   /* 14 + 2×10 padding + 2×1 border = 36px */
  height: calc(var(--hl-fs-md) + 22px);
}
.hl-btn--icon.hl-btn--sm {
  padding: 7px;
  width: calc(var(--hl-fs-sm) + 16px);   /* 12.5 + 2×7 padding + 2×1 border = 28.5px */
  height: calc(var(--hl-fs-sm) + 16px);
}
.hl-btn--icon.hl-btn--lg {
  padding: 14px;
  width: calc(var(--hl-fs-lg) + 30px);   /* 17 + 2×14 padding + 2×1 border = 47px */
  height: calc(var(--hl-fs-lg) + 30px);
}

/* Inline link-button — for tiny "Download PDF" actions */
.hl-action {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: transparent;
  color: var(--hl-text-muted);
  border: none;
  cursor: pointer;
  padding: 8px var(--hl-sp-3);
  border-radius: var(--hl-r-sm);
  font: 500 13px/1 var(--hl-font-sans);
  transition: background var(--hl-dur-fast) var(--hl-ease),
              color var(--hl-dur-fast) var(--hl-ease);
}
.hl-action:hover {
  background: rgba(255,255,255,0.05);
  color: var(--hl-text);
}

/* ── 5.2 CARD ──────────────────────────────────── */
.hl-card {
  background: var(--hl-bg-elev);
  border: 1px solid var(--hl-border);
  border-radius: var(--hl-r-lg);
  box-shadow: var(--hl-shadow-card);
  overflow: hidden;
  position: relative;
}
.hl-card--flush  { overflow: visible; }
.hl-card--accent { border-color: var(--hl-accent-glow); }
.hl-card--feature {
  background: linear-gradient(135deg, rgba(84,110,250,0.08) 0%, rgba(249,115,22,0.06) 100%);
  border-color: rgba(84,110,250,0.20);
}

.hl-card__header {
  padding: var(--hl-sp-5) var(--hl-sp-6) var(--hl-sp-4);
  border-bottom: 1px solid var(--hl-border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--hl-sp-4);
}
.hl-card__body   { padding: var(--hl-sp-6); }
.hl-card__body--tight { padding: var(--hl-sp-5) var(--hl-sp-6); }
.hl-card__meta {
  border-top: 1px solid var(--hl-border);
  padding: var(--hl-sp-4) var(--hl-sp-6);
  background: rgba(255,255,255,0.015);
}
.hl-card__footer {
  border-top: 1px solid var(--hl-border);
  padding: var(--hl-sp-3) var(--hl-sp-4);
  display: flex;
  flex-wrap: wrap;
  gap: var(--hl-sp-2);
}

/* ── 5.3 BADGE ──────────────────────────────────── */
.hl-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: var(--hl-r-pill);
  font-size: var(--hl-fs-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  border: 1px solid transparent;
  white-space: nowrap;
}
.hl-badge--neutral { background: rgba(255,255,255,0.05); color: var(--hl-text-2); border-color: var(--hl-border-strong); }
.hl-badge--success { background: var(--hl-success-soft); color: var(--hl-success); border-color: rgba(74,222,128,0.20); }
.hl-badge--warning { background: var(--hl-warning-soft); color: var(--hl-warning); border-color: rgba(251,191,36,0.20); }
.hl-badge--danger  { background: var(--hl-danger-soft);  color: var(--hl-danger);  border-color: rgba(239,68,68,0.20); }
.hl-badge--info    { background: var(--hl-info-soft);    color: var(--hl-info);    border-color: rgba(96,165,250,0.20); }
.hl-badge--accent  { background: var(--hl-accent-soft);  color: var(--hl-accent);  border-color: rgba(249,115,22,0.20); }

.hl-badge__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}

/* ── 5.4 CHIP (small inline tag) ──────────────────────────────── */
.hl-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  border-radius: var(--hl-r-pill);
  background: rgba(255,255,255,0.05);
  color: var(--hl-text-2);
  border: 1px solid var(--hl-border-strong);
  font-size: 11.5px;
  font-weight: 500;
  white-space: nowrap;
}
.hl-chip--success { background: var(--hl-success-soft); color: var(--hl-success); border-color: rgba(74,222,128,0.20); }
.hl-chip--info    { background: var(--hl-info-soft);    color: var(--hl-info);    border-color: rgba(96,165,250,0.20); }
.hl-chip--accent  { background: var(--hl-accent-soft);  color: var(--hl-accent);  border-color: rgba(249,115,22,0.20); }

/* ── 5.5 FORM CONTROLS ───────────────────────────── */
.hl-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.hl-field__label {
  font-size: var(--hl-fs-sm);
  font-weight: 500;
  color: var(--hl-text-2);
}
.hl-field__hint {
  font-size: var(--hl-fs-sm);
  color: var(--hl-text-muted);
}
.hl-field__error {
  font-size: var(--hl-fs-sm);
  color: var(--hl-danger);
}

.hl-input,
.hl-select,
.hl-textarea {
  display: block;
  width: 100%;
  padding: 11px var(--hl-sp-3);
  background: var(--hl-bg);
  color: var(--hl-text);
  border: 1px solid var(--hl-border-strong);
  border-radius: var(--hl-r-md);
  font: 400 var(--hl-fs-md)/1.4 var(--hl-font-sans);
  transition: border-color var(--hl-dur-fast) var(--hl-ease),
              background var(--hl-dur-fast) var(--hl-ease),
              box-shadow var(--hl-dur-fast) var(--hl-ease);
}
.hl-input:hover,
.hl-select:hover,
.hl-textarea:hover { border-color: rgba(255,255,255,0.16); }

.hl-input:focus,
.hl-select:focus,
.hl-textarea:focus {
  outline: none;
  border-color: var(--hl-border-focus);
  box-shadow: var(--hl-ring);
}

.hl-input::placeholder,
.hl-textarea::placeholder { color: var(--hl-text-faint); }

.hl-textarea { resize: vertical; min-height: 92px; line-height: 1.5; }

.hl-select {
  appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' stroke='%239ca3af' stroke-width='1.6' fill='none' stroke-linecap='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 36px;
}

.hl-input-group {
  display: flex;
  align-items: center;
  background: var(--hl-bg);
  border: 1px solid var(--hl-border-strong);
  border-radius: var(--hl-r-md);
  padding: 0 12px;
  transition: border-color var(--hl-dur-fast) var(--hl-ease),
              box-shadow var(--hl-dur-fast) var(--hl-ease);
}
.hl-input-group:focus-within {
  border-color: var(--hl-border-focus);
  box-shadow: var(--hl-ring);
}
.hl-input-group__addon {
  color: var(--hl-text-muted);
  font-size: var(--hl-fs-sm);
  flex-shrink: 0;
}
.hl-input-group .hl-input {
  border: none;
  background: transparent;
  padding-left: 8px;
  padding-right: 8px;
}
.hl-input-group .hl-input:focus { box-shadow: none; }

/* Checkbox / Radio — minimal */
.hl-check {
  display: inline-flex;
  align-items: center;
  gap: var(--hl-sp-2);
  cursor: pointer;
  user-select: none;
  font-size: var(--hl-fs-md);
  color: var(--hl-text-2);
}
.hl-check input { accent-color: var(--hl-accent); width: 16px; height: 16px; }

/* Switch */
.hl-switch {
  position: relative;
  width: 38px;
  height: 22px;
  background: var(--hl-bg-elev-2);
  border-radius: var(--hl-r-pill);
  cursor: pointer;
  transition: background var(--hl-dur-fast) var(--hl-ease);
  flex-shrink: 0;
}
.hl-switch::after {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: 16px;
  height: 16px;
  background: #fff;
  border-radius: 50%;
  transition: transform var(--hl-dur-fast) var(--hl-ease);
}
.hl-switch--on { background: var(--hl-accent); }
.hl-switch--on::after { transform: translateX(16px); }

/* Segmented control (radio group) */
.hl-segmented {
  display: inline-flex;
  background: var(--hl-bg);
  border: 1px solid var(--hl-border-strong);
  border-radius: var(--hl-r-md);
  padding: 3px;
  gap: 2px;
}
.hl-segmented__item {
  padding: 6px 14px;
  border-radius: var(--hl-r-sm);
  font: 500 var(--hl-fs-sm)/1 var(--hl-font-sans);
  background: transparent;
  color: var(--hl-text-muted);
  border: none;
  cursor: pointer;
  transition: background var(--hl-dur-fast) var(--hl-ease),
              color var(--hl-dur-fast) var(--hl-ease);
}
.hl-segmented__item:hover { color: var(--hl-text); }
.hl-segmented__item--active {
  background: var(--hl-bg-elev-2);
  color: var(--hl-text);
}

/* Choice — radio-pill group. Separate selectable pills (unlike the joined
   .hl-segmented bar), each wrapping a native radio for keyboard + form support.
   For single-select questions / surveys where options carry their own labels. */
.hl-choice {
  display: flex;
  flex-wrap: wrap;
  gap: var(--hl-sp-2);
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0;
}
.hl-choice__opt {
  display: inline-flex;
  align-items: center;
  gap: var(--hl-sp-2);
  padding: 8px 16px;
  border: 1px solid var(--hl-border-strong);
  border-radius: var(--hl-r-pill);
  background: var(--hl-bg);
  color: var(--hl-text-2);
  font: 600 var(--hl-fs-sm)/1 var(--hl-font-sans);
  cursor: pointer;
  transition: border-color var(--hl-dur-fast) var(--hl-ease),
              background var(--hl-dur-fast) var(--hl-ease),
              color var(--hl-dur-fast) var(--hl-ease);
}
.hl-choice__opt:hover { border-color: var(--hl-border-focus); color: var(--hl-text); }
.hl-choice__opt:focus-within {
  border-color: var(--hl-border-focus);
  box-shadow: var(--hl-ring);
}
.hl-choice__opt input { accent-color: var(--hl-accent); width: 15px; height: 15px; margin: 0; cursor: pointer; }
.hl-choice__opt--on {
  border-color: var(--hl-accent);
  background: var(--hl-accent-soft);
  color: var(--hl-text);
}

/* ── 5.6 ALERT ──────────────────────────────────── */
.hl-alert {
  display: flex;
  gap: var(--hl-sp-3);
  padding: var(--hl-sp-4);
  border-radius: var(--hl-r-md);
  background: var(--hl-info-soft);
  border: 1px solid rgba(96,165,250,0.20);
  color: var(--hl-text-2);
  font-size: var(--hl-fs-md);
  line-height: var(--hl-lh-snug);
}
.hl-alert--success { background: var(--hl-success-soft); border-color: rgba(74,222,128,0.20); }
.hl-alert--warning { background: var(--hl-warning-soft); border-color: rgba(251,191,36,0.20); }
.hl-alert--danger  { background: var(--hl-danger-soft);  border-color: rgba(239,68,68,0.20); }
.hl-alert__icon { flex-shrink: 0; color: var(--hl-info); margin-top: 2px; }
.hl-alert--success .hl-alert__icon { color: var(--hl-success); }
.hl-alert--warning .hl-alert__icon { color: var(--hl-warning); }
.hl-alert--danger  .hl-alert__icon { color: var(--hl-danger); }

/* ── 5.7 LIST GROUP (used for unlocked features etc) ─── */
.hl-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 11px; }
.hl-list__item {
  display: flex;
  align-items: center;
  gap: var(--hl-sp-3);
  color: var(--hl-text-2);
  font-size: var(--hl-fs-md);
}
.hl-list__item--locked { color: var(--hl-text-faint); }
.hl-list__item-value {
  color: var(--hl-text-muted);
  font-size: var(--hl-fs-sm);
  font-variant-numeric: tabular-nums;
}

.hl-dot {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-size: 11px;
}
.hl-dot--success { background: var(--hl-success-soft); color: var(--hl-success); }
.hl-dot--locked  { background: rgba(255,255,255,0.04); color: var(--hl-text-dim); }
.hl-dot--accent  { background: var(--hl-accent-soft); color: var(--hl-accent); }

/* ── 5.8 SUCCESS MARK (animated, for confirmations) ─── */
.hl-mark {
  width: 84px;
  height: 84px;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%,
              rgba(249,115,22,0.28),
              rgba(249,115,22,0.12) 60%,
              transparent 80%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  animation: hl-mark-in 0.6s var(--hl-ease) both;
}
.hl-mark__inner {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background: var(--hl-accent-soft);
  border: 1px solid var(--hl-accent-glow);
  color: var(--hl-accent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 12px 28px -10px var(--hl-accent-glow);
  font-size: 28px;
}
.hl-mark--info {
  background: radial-gradient(circle at 30% 30%, rgba(96,165,250,0.28), rgba(96,165,250,0.12) 60%, transparent 80%);
}
.hl-mark--info .hl-mark__inner {
  background: var(--hl-info-soft);
  border-color: rgba(96,165,250,0.40);
  color: var(--hl-info);
  box-shadow: 0 12px 28px -10px rgba(96,165,250,0.6);
}
.hl-mark--violet {
  background: radial-gradient(circle at 30% 30%, rgba(167,139,250,0.28), rgba(167,139,250,0.12) 60%, transparent 80%);
}
.hl-mark--violet .hl-mark__inner {
  background: var(--hl-violet-soft);
  border-color: rgba(167,139,250,0.40);
  color: var(--hl-violet);
  box-shadow: 0 12px 28px -10px rgba(167,139,250,0.6);
}

/* ── 5.9 CARD BRAND CHIP (Visa/MC etc) ───────────── */
.hl-cardbrand {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 24px;
  border-radius: 4px;
  color: #fff;
  font: italic 800 9px/1 var(--hl-font-sans);
  letter-spacing: 0.04em;
  box-shadow: var(--hl-shadow-inset);
  flex-shrink: 0;
}
.hl-cardbrand--visa       { background: linear-gradient(135deg, #1a1f71 0%, #2a3084 100%); }
.hl-cardbrand--mastercard { background: linear-gradient(135deg, #000 0%, #1a1a1a 100%); }
.hl-cardbrand--amex       { background: linear-gradient(135deg, #006fcf 0%, #0884db 100%); }

/* ── 5.10 META PAIR (label + value, used in receipts) ─ */
.hl-meta {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.hl-meta__label {
  font-size: var(--hl-fs-xs);
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--hl-text-faint);
}
.hl-meta__value { color: var(--hl-text-2); font-size: 13.5px; line-height: var(--hl-lh-snug); }
.hl-meta__value-sub { color: var(--hl-text-faint); font-size: 12.5px; }

/* ── 5.11 KEY/VALUE ROW (money breakdowns) ─────── */
.hl-kv {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 4px 0;
}
.hl-kv__key   { color: var(--hl-text-muted); font-size: 13.5px; }
.hl-kv__value { color: var(--hl-text-2); font-size: var(--hl-fs-md); font-weight: 500; font-variant-numeric: tabular-nums; }
.hl-kv--total .hl-kv__key   { color: var(--hl-text-2); font-size: var(--hl-fs-md); font-weight: 600; }
.hl-kv--total .hl-kv__value { color: var(--hl-text); font-size: var(--hl-fs-xl); font-weight: 700; letter-spacing: -0.02em; }

/* ── 5.12 ICON BUBBLE (accent square holding an icon) ─── */
.hl-iconbubble {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: var(--hl-accent-soft);
  color: var(--hl-accent);
  flex-shrink: 0;
}
.hl-iconbubble--sm { width: 32px; height: 32px; border-radius: 8px; }
.hl-iconbubble--xs { width: 24px; height: 24px; border-radius: 6px; }
.hl-iconbubble--info    { background: var(--hl-info-soft);    color: var(--hl-info); }
.hl-iconbubble--violet  { background: var(--hl-violet-soft);  color: var(--hl-violet); }
.hl-iconbubble--success { background: var(--hl-success-soft); color: var(--hl-success); }
.hl-iconbubble--neutral { background: rgba(255,255,255,0.04); color: var(--hl-text-2); }

/* ── 5.13 NEXT-STEP LINK ROW ─────────────────────── */
.hl-nextstep {
  display: flex;
  align-items: center;
  gap: var(--hl-sp-3);
  padding: 11px var(--hl-sp-3);
  border-radius: var(--hl-r-md);
  background: transparent;
  border: 1px solid rgba(255,255,255,0.04);
  cursor: pointer;
  transition: background var(--hl-dur-fast) var(--hl-ease),
              border-color var(--hl-dur-fast) var(--hl-ease);
  text-decoration: none;
  color: inherit;
}
.hl-nextstep:hover {
  background: rgba(255,255,255,0.04);
  border-color: var(--hl-border-strong);
  text-decoration: none;
}
.hl-nextstep__body { flex: 1; min-width: 0; }
.hl-nextstep__title { color: var(--hl-text); font-size: var(--hl-fs-md); font-weight: 500; }
.hl-nextstep__meta  { color: var(--hl-text-muted); font-size: 12.5px; line-height: 1.5; margin-top: 2px; }
.hl-nextstep__chev  { color: var(--hl-text-faint); transition: color var(--hl-dur-fast) var(--hl-ease); }
.hl-nextstep:hover .hl-nextstep__chev { color: var(--hl-text); }

/* ── 5.13a BACK LINK (the backward sibling of the next-step row) ───
   The page-level "return to the parent page" affordance. Always the first
   child of the page shell, on its own row, above the header — never inside a
   header, never inline with a title, and above any context banner. It owns
   its own bottom margin, so callers must not wrap it in a spacing div.
   Markup — but prefer the component, <BackLink Href="…" Text="…" />, which
   renders exactly this and fixes the icon so callers can't drift:
     <nav class="hl-backlink-nav" aria-label="Breadcrumb">
       <a class="hl-backlink" href="/feed">
         <i class="fa-duotone fa-regular fa-arrow-left-long"></i>
         <span>Back to Feed</span>
       </a>
     </nav>
   The indigo is the brand blue shared with .hl-card--feature, which has no
   token of its own. */
.hl-backlink-nav { margin-bottom: var(--hl-sp-5); }
.hl-backlink {
  display: inline-flex;
  align-items: center;
  gap: var(--hl-sp-2);
  padding: 6px var(--hl-sp-3);
  border-radius: var(--hl-r-pill);
  border: 1px solid rgba(84, 110, 250, 0.35);
  background: rgba(84, 110, 250, 0.08);
  color: #93c5fd;
  font-size: var(--hl-fs-sm);
  font-weight: 500;
  text-decoration: none;
  transition: background var(--hl-dur-fast) var(--hl-ease),
              border-color var(--hl-dur-fast) var(--hl-ease),
              color var(--hl-dur-fast) var(--hl-ease),
              transform var(--hl-dur-fast) var(--hl-ease);
}
.hl-backlink:hover {
  background: rgba(84, 110, 250, 0.18);
  border-color: rgba(84, 110, 250, 0.6);
  color: #c7d2fe;
  text-decoration: none;
  transform: translateX(-2px);
}
.hl-backlink i { font-size: 12px; }
@media (prefers-reduced-motion: reduce) {
  .hl-backlink:hover { transform: none; }
}

/* ── 5.14 STEPS (progress stepper — active step pulses) ───
   Markup: alternate .hl-steps__step and .hl-steps__line.
     <div class="hl-steps">
       <div class="hl-steps__step hl-steps__step--complete">
         <span class="hl-steps__node"><i class="fa-solid fa-check"></i></span>
         <span class="hl-steps__label">Draft</span>
       </div>
       <div class="hl-steps__line hl-steps__line--active"></div>   (green→accent, leads into current)
       <div class="hl-steps__step hl-steps__step--current">
         <span class="hl-steps__node">2</span>
         <span class="hl-steps__label">Review</span>
       </div>
       <div class="hl-steps__line"></div>                          (faint, upcoming)
       <div class="hl-steps__step">
         <span class="hl-steps__node">3</span>
         <span class="hl-steps__label">Publish</span>
       </div>
     </div>
   Step states: (default = upcoming), --complete, --current.
   Line states:  (default = upcoming/faint), --complete (solid green), --active (green→accent).
   Semantic <ol>/<li> works too (the list is reset); wrap a step's node + label in
   <a class="hl-steps__link"> to make it navigable. */
.hl-steps {
  display: flex;
  align-items: flex-start;
  width: 100%;
  list-style: none;   /* lets the stepper be a semantic <ol>; neutralizes list defaults */
  margin: 0;
  padding: 0;
}
.hl-steps__step {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--hl-sp-2);
  flex: 0 0 auto;
}
/* Navigable step — an <a> or <button> wrapping the node + label; gentle lift + label
   brighten on hover. Button-reset props keep a <button> visually identical to the <a> form. */
.hl-steps__link {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: var(--hl-sp-2);
  text-decoration: none;
  color: inherit;
  cursor: pointer;
  border-radius: var(--hl-r-sm);
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  transition: transform var(--hl-dur-fast) var(--hl-ease);
}
.hl-steps__link:hover { transform: translateY(-1px); text-decoration: none; }
.hl-steps__link:hover .hl-steps__label { color: var(--hl-text); }
.hl-steps__node {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  background: var(--hl-bg);
  border: 1.5px solid var(--hl-border-strong);
  color: var(--hl-text-faint);
  transition: border-color var(--hl-dur-fast) var(--hl-ease),
              color var(--hl-dur-fast) var(--hl-ease),
              box-shadow var(--hl-dur) var(--hl-ease);
}
.hl-steps__label {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--hl-text-faint);
  white-space: nowrap;
  transition: color var(--hl-dur-fast) var(--hl-ease);
}
.hl-steps__line {
  flex: 1 1 auto;
  height: 1.5px;
  min-width: 24px;
  margin-top: 13px;            /* centers the line on the 28px node */
  border-radius: 2px;
  background: var(--hl-border-strong);
}

/* Completed step — green */
.hl-steps__step--complete .hl-steps__node {
  background: var(--hl-success-soft);
  border-color: rgba(74, 222, 128, 0.45);
  color: var(--hl-success);
}
.hl-steps__step--complete .hl-steps__label { color: var(--hl-success); }

/* Current step — accent dot that pulses to anchor "you are here" */
.hl-steps__step--current .hl-steps__node {
  background: var(--hl-accent-soft);
  border-color: var(--hl-accent);
  color: #fff;
  box-shadow: 0 0 0 6px rgba(249, 115, 22, 0.10),
              0 0 24px -4px rgba(249, 115, 22, 0.45);
  animation: hl-step-pulse 2.4s ease-in-out infinite;
}
.hl-steps__step--current .hl-steps__label { color: var(--hl-text); }

/* Connector states */
.hl-steps__line--complete { background: var(--hl-success); }
.hl-steps__line--active {
  background: linear-gradient(90deg, var(--hl-success) 0%, var(--hl-success) 55%, var(--hl-accent) 100%);
}

/* ── 5.15 TOPBAR / NAV (Bootstrap navbar replacement) ── */
.hl-topbar {
  position: sticky;
  top: 0;
  z-index: 50;
  height: 64px;
  background: var(--hl-bg-overlay);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--hl-border);
}
.hl-topbar__inner {
  height: 100%;
  max-width: var(--hl-container);
  margin: 0 auto;
  padding: 0 var(--hl-sp-8);
  display: flex;
  align-items: center;
  gap: var(--hl-sp-6);
}
.hl-navlink {
  color: var(--hl-text-muted);
  font-size: var(--hl-fs-md);
  font-weight: 500;
  padding: 8px 12px;
  border-radius: var(--hl-r-sm);
  text-decoration: none;
  transition: color var(--hl-dur-fast) var(--hl-ease),
              background var(--hl-dur-fast) var(--hl-ease);
}
.hl-navlink:hover { color: var(--hl-text); background: rgba(255,255,255,0.04); text-decoration: none; }
.hl-navlink--active { color: var(--hl-text); background: rgba(255,255,255,0.06); }

/* ── 5.15 TABLE ──────────────────────────────────── */
.hl-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--hl-fs-md);
}
.hl-table thead th {
  text-align: left;
  font-size: var(--hl-fs-xs);
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--hl-text-faint);
  padding: 10px var(--hl-sp-4);
  border-bottom: 1px solid var(--hl-border);
}
.hl-table tbody td {
  padding: 14px var(--hl-sp-4);
  color: var(--hl-text-2);
  border-bottom: 1px solid var(--hl-border);
}
.hl-table tbody tr:hover td { background: rgba(255,255,255,0.02); }
.hl-table tbody tr:last-child td { border-bottom: 0; }

/* ── 5.16 TOOLTIP (CSS-only, no JS) ──────────────── */
.hl-tooltip {
  position: relative;
  display: inline-block;
}
.hl-tooltip::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  background: var(--hl-bg-elev-2);
  border: 1px solid var(--hl-border-strong);
  color: var(--hl-text);
  font-size: var(--hl-fs-sm);
  padding: 6px 10px;
  border-radius: var(--hl-r-sm);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--hl-dur-fast) var(--hl-ease),
              transform var(--hl-dur-fast) var(--hl-ease);
  z-index: 10;
}
.hl-tooltip:hover::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* ── 5.17 SPINNER + LOADING ──────────────────────────
   A bare ring spinner, plus a centered loading block (spinner + caption)
   for full-area "fetching…" states. Markup:
     <div class="hl-loading">
       <span class="hl-spinner hl-spinner--lg" role="status" aria-label="Loading"></span>
       <p class="hl-loading__text">Loading your feed…</p>
     </div> */
.hl-spinner {
  display: inline-block;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 3px solid var(--hl-border-strong);
  border-top-color: var(--hl-accent);
  animation: hl-spin 0.7s linear infinite;
  flex-shrink: 0;
  vertical-align: middle;
}
.hl-spinner--sm { width: 18px; height: 18px; border-width: 2px; }
.hl-spinner--lg { width: 44px; height: 44px; border-width: 4px; }
.hl-spinner--info   { border-top-color: var(--hl-info); }
.hl-spinner--violet { border-top-color: var(--hl-violet); }

.hl-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--hl-sp-4);
  padding: var(--hl-sp-12) var(--hl-sp-6);
  text-align: center;
}
.hl-loading__text {
  font-size: var(--hl-fs-md);
  color: var(--hl-text-muted);
}

/* ── 5.18 STATE (empty / error / success full-area block) ───
   Centered icon-bubble + title + message + optional actions, for empty
   collections and graceful failure screens. Markup:
     <div class="hl-state">
       <span class="hl-state__icon hl-state__icon--danger"><i class="fa-solid fa-cloud-slash"></i></span>
       <h2 class="hl-state__title">Something went wrong</h2>
       <p class="hl-state__message">We couldn't load your feed. Please try again.</p>
       <div class="hl-state__actions">
         <button class="hl-btn hl-btn--primary">Try again</button>
       </div>
     </div> */
.hl-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--hl-sp-4);
  padding: var(--hl-sp-12) var(--hl-sp-6);
  text-align: center;
  max-width: 460px;
  margin: 0 auto;
}
.hl-state__icon {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 26px;
  background: rgba(255, 255, 255, 0.04);
  color: var(--hl-text-muted);
  flex-shrink: 0;
}
.hl-state__icon--danger { background: var(--hl-danger-soft); color: var(--hl-danger); }
.hl-state__icon--accent { background: var(--hl-accent-soft); color: var(--hl-accent); }
.hl-state__icon--info   { background: var(--hl-info-soft);   color: var(--hl-info); }
.hl-state__title {
  font-size: var(--hl-fs-xl);
  font-weight: 600;
  color: var(--hl-text);
  letter-spacing: -0.02em;
}
.hl-state__message {
  font-size: var(--hl-fs-md);
  color: var(--hl-text-muted);
  line-height: var(--hl-lh-relaxed);
  max-width: 40ch;
}
.hl-state__actions {
  display: flex;
  gap: var(--hl-sp-3);
  margin-top: var(--hl-sp-2);
  flex-wrap: wrap;
  justify-content: center;
}

/* ── 5.19 PAGE HEADER (title + optional eyebrow/subtitle/actions) ───
   The standard header every list/overview page opens with. One type
   scale for all pages — deliberately no size modifier. The eyebrow is
   the existing .hl-eyebrow, not a header-specific class. Markup:
     <div class="hl-page-header">
       <div class="hl-page-header__text">
         <div class="hl-eyebrow hl-eyebrow--accent">Moderation</div>
         <h1 class="hl-page-header__title">Moderate feedback</h1>
         <p class="hl-page-header__subtitle">Review incoming responses.</p>
       </div>
       <div class="hl-page-header__actions">
         <a class="hl-btn hl-btn--primary">New topic</a>
       </div>
     </div>
   When something sits inline beside the title — a team badge, a status
   chip — wrap the two in a title row. Only emit the row when there is
   a suffix; a lone title needs no flex container:
     <div class="hl-page-header__title-row">
       <h1 class="hl-page-header__title">Manage topics</h1>
       <span class="hl-badge hl-badge--info">Vectorsoft</span>
     </div>
   Prefer the <PageHeader> Razor component over hand-writing this. */
.hl-page-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--hl-sp-3);
  margin-bottom: var(--hl-sp-6);
}
.hl-page-header__text {
  /* min-width:0 lets a long title wrap instead of forcing the actions
     cluster off the row. */
  min-width: 0;
}
.hl-page-header__title {
  margin: 0;
  color: var(--hl-text);
  font-family: var(--hl-font-sans);
  font-size: var(--hl-fs-xl);
  font-weight: 600;
  line-height: var(--hl-lh-tight);
  letter-spacing: -0.01em;
  /* Several pages put user-supplied text here — a team name, a topic
     name, an invoice heading. Without this a long unbroken string
     overflows the header instead of wrapping. */
  overflow-wrap: anywhere;
}
/* Title plus an inline suffix. align-items:center rather than baseline:
   the suffix is usually a badge or chip, and baseline alignment hangs
   those below the title's baseline instead of centring on it. */
.hl-page-header__title-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--hl-sp-2);
  min-width: 0;
}
.hl-page-header__subtitle {
  margin: var(--hl-sp-1) 0 0;
  color: var(--hl-text-muted);
  font-family: var(--hl-font-sans);
  font-size: var(--hl-fs-sm);
  line-height: var(--hl-lh-snug);
}
/* Eyebrow sits above the title; .hl-eyebrow carries the type, the
   header only owns the gap beneath it. */
.hl-page-header__text > .hl-eyebrow {
  margin-bottom: var(--hl-sp-1);
}
.hl-page-header__actions {
  display: flex;
  align-items: center;
  gap: var(--hl-sp-2);
  flex-wrap: wrap;
  flex-shrink: 0;
}

@media (max-width: 860px) {
  .hl-page-header {
    align-items: flex-start;
    flex-direction: column;
  }
}

/* ── 5.20 MARKETING HERO (eyebrow + display headline + lead) ───────
   The second header shape. .hl-page-header is the app's — one fixed
   22px scale, title beside its actions. This one is editorial: display
   type, a lead paragraph, CTAs beneath.

   It styles the *text column only*. Every page that uses it wraps the
   hero in its own grid or section — a two-column layout with a product
   image, a glow backdrop, a max-width — and that stays page-local,
   because none of it is shared. Markup:
     <div class="hl-hero hl-hero--lg">
       <div class="hl-eyebrow hl-eyebrow--accent">About Honestli</div>
       <h1 class="hl-hero__title">
         Feedback without <span class="hl-hero__accent">the fallout</span>.
       </h1>
       <p class="hl-hero__lead">Anonymous, good-faith feedback.</p>
       <div class="hl-hero__actions"> … </div>
     </div>
   Prefer the <Hero> Razor component over hand-writing this.

   SIZE. Unlike .hl-page-header this does take a size modifier, because
   the nine pages it replaced were not nine sizes — they were four
   near-exact pairs, and collapsing them to one would have redesigned
   eight pages rather than refactoring them:
     --xl  Home, Anonymous feedback          (the two landing heroes)
     --lg  About, How it works               (were byte-identical)
     (default)  Contact, Pricing, Privacy    (Pricing/Privacy identical)
     --sm  Stories, Upgrade                  (both flat 32px)
   Each tier's value is one of the pair's, not an average. The lead
   colour and size track the tier too: the display tiers ran a brighter
   --hl-text-2 lead, the smaller ones --hl-text-muted. */
.hl-hero {
  --hl-hero-fs:         clamp(28px, 3.6vw, 44px);
  --hl-hero-lh:         1.1;
  --hl-hero-ls:         -0.02em;
  /* 15.5px has no token: the scale jumps 14px (--hl-fs-md) to 17px
     (--hl-fs-lg) with nothing between, and the five leads that landed
     here spread 14.5–16px. Promoting a step into the global scale is a
     bigger call than this component; it stays hero-local until then. */
  --hl-hero-lead-fs:    15.5px;
  --hl-hero-lead-color: var(--hl-text-muted);
}
.hl-hero--xl {
  --hl-hero-fs:         clamp(40px, 5vw, 64px);
  --hl-hero-lh:         1.04;
  --hl-hero-ls:         -0.03em;
  --hl-hero-lead-fs:    var(--hl-fs-lg);
  --hl-hero-lead-color: var(--hl-text-2);
}
.hl-hero--lg {
  --hl-hero-fs:         clamp(36px, 4.5vw, 58px);
  --hl-hero-lh:         1.06;
  --hl-hero-ls:         -0.03em;
  --hl-hero-lead-fs:    var(--hl-fs-lg);
  --hl-hero-lead-color: var(--hl-text-2);
}
.hl-hero--sm {
  --hl-hero-fs:         var(--hl-fs-2xl);
  --hl-hero-lh:         1.15;
}

.hl-hero__title {
  margin: 0;
  color: var(--hl-text);
  font-family: var(--hl-font-sans);
  font-size: var(--hl-hero-fs);
  font-weight: 700;
  line-height: var(--hl-hero-lh);
  letter-spacing: var(--hl-hero-ls);
}
/* Mid-sentence colour break in a headline — "Honest answers." set against
   the rest of the line. Two accents so a headline can alternate. */
.hl-hero__accent      { color: var(--hl-accent); }
.hl-hero__accent--alt { color: var(--hl-accent-blue); }

.hl-hero__lead {
  margin: var(--hl-sp-5) 0 0;
  color: var(--hl-hero-lead-color);
  font-size: var(--hl-hero-lead-fs);
  line-height: var(--hl-lh-relaxed);
  max-width: 56ch;
}
/* Emphasis inside a lead lifts to full white — every page did this. */
.hl-hero__lead strong { color: var(--hl-text); }

.hl-hero__actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--hl-sp-3);
  margin-top: var(--hl-sp-7);
}
/* Trailing row beneath the CTAs — trust signals, a last-updated date,
   feature pills. Deliberately loose: pages put different things here. */
.hl-hero__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--hl-sp-6);
  margin-top: var(--hl-sp-7);
  color: var(--hl-text-muted);
  font-size: var(--hl-fs-md);
}
/* Most meta items are an icon plus a word; this keeps the two aligned
   without every page re-declaring the flex row. A page that puts a real
   container here (a pill group, say) overrides it from its own scoped
   sheet, which outranks this by one class. */
.hl-hero__meta > * {
  display: inline-flex;
  align-items: center;
  gap: var(--hl-sp-2);
}

/* The kicker owns its own type; the hero owns only the gap beneath it.
   .hl-badge is here too because the two landing heroes open with a badge
   rather than an eyebrow — sentence case with a status dot, not small caps. */
.hl-hero > .hl-eyebrow,
.hl-hero > .hl-badge {
  margin-bottom: var(--hl-sp-4);
}

.hl-hero--center {
  margin-inline: auto;
  text-align: center;
}
.hl-hero--center .hl-hero__lead { margin-inline: auto; }
.hl-hero--center .hl-hero__actions,
.hl-hero--center .hl-hero__meta { justify-content: center; }

/* -------------------------------------------------------------
   6. ANIMATIONS
   ------------------------------------------------------------- */
@keyframes hl-mark-in {
  0%   { opacity: 0; transform: scale(0.7); }
  70%  { opacity: 1; transform: scale(1.06); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes hl-fade-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
.hl-anim-fade-in { animation: hl-fade-in 0.4s var(--hl-ease) both; }

/* Spinner ring rotation — used by .hl-spinner */
@keyframes hl-spin { to { transform: rotate(360deg); } }

/* Breathing status dot — used by .hl-eyebrow__dot--pulse */
@keyframes hl-dot-pulse {
  0%, 100% { opacity: 1;    transform: scale(1); }
  50%      { opacity: 0.55; transform: scale(0.82); }
}

/* Active-step "you are here" pulse — used by .hl-steps__step--current */
@keyframes hl-step-pulse {
  0%, 100% { box-shadow: 0 0 0 6px rgba(249, 115, 22, 0.10),
                          0 0 24px -4px rgba(249, 115, 22, 0.45); }
  50%      { box-shadow: 0 0 0 10px rgba(249, 115, 22, 0.04),
                          0 0 28px -2px rgba(249, 115, 22, 0.55); }
}

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