/* ============================================================================
   AURORA — Helion's design system, and the product's only skin since
   2026-08-17 (Meridian retired; its final two-skin state is git tag
   `meridian-final`). Structure of this file: the original Meridian plumbing
   first (kept because every component's bones live in it), then THE AURORA
   LAYER at the end re-skinning it — the layer must stay last, since at equal
   specificity it wins on source order alone. Aurora's rules live in the
   layer's comments and in app/views/helion/README.md under "Aurora".
   ========================================================================== */

/* Helion — Aplify v2 UI */
/* Design system: "Meridian" — brand-ink navy sidebar, blue -> cyan gradient accent, soft/borderless cards. */

@font-face { font-family: 'Archivo'; font-weight: 600; font-style: normal; font-display: swap; src: url("/assets/fonts/archivo-600-cafc4a45.woff2") format('woff2'); }
@font-face { font-family: 'Archivo'; font-weight: 800; font-style: normal; font-display: swap; src: url("/assets/fonts/archivo-800-ab4513af.woff2") format('woff2'); }
@font-face { font-family: 'IBM Plex Sans'; font-weight: 400; font-style: normal; font-display: swap; src: url("/assets/fonts/plexsans-400-64251e64.woff2") format('woff2'); }
@font-face { font-family: 'IBM Plex Sans'; font-weight: 500; font-style: normal; font-display: swap; src: url("/assets/fonts/plexsans-500-290aaea2.woff2") format('woff2'); }
@font-face { font-family: 'IBM Plex Sans'; font-weight: 600; font-style: normal; font-display: swap; src: url("/assets/fonts/plexsans-600-99b2fa32.woff2") format('woff2'); }
@font-face { font-family: 'IBM Plex Mono'; font-weight: 500; font-style: normal; font-display: swap; src: url("/assets/fonts/plexmono-500-3f7bbac1.woff2") format('woff2'); }

* { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  --helion-sidebar-rail: 104px;
  --helion-sidebar-width: 240px;
  --helion-header-height: 68px;
  --helion-nav-bleed: 18px;   /* literal overhang past the sidebar's right edge */
  --helion-content-gutter: 3.5rem;  /* left gutter on page content, clear of the bleeding pill */
  --helion-card-gap: var(--space-5);  /* single rhythm between cards, whether gridded or stacked */

  /* Spacing scale. Premium interfaces feel calm largely because spacing REPEATS — the eye finds a
     rhythm even when it cannot name one. Reach for a step here rather than inventing a value;
     a bespoke number is nearly always a step in disguise. */
  --space-1: 0.25rem;   /*  4px */
  --space-2: 0.5rem;    /*  8px */
  --space-3: 0.75rem;   /* 12px */
  --space-4: 1rem;      /* 16px */
  --space-5: 1.5rem;    /* 24px */
  --space-6: 2rem;      /* 32px */
  --space-7: 3rem;      /* 48px */
  --space-8: 4rem;      /* 64px */

  /* Measure: prose beyond ~75 characters is tiring to read, and unbounded prose is the clearest
     signal that a layout was never considered. Content is capped too, so a row's information does
     not scatter across a wide monitor. */
  /* Type scale. Font sizes had the same problem as spacing — 0.66/0.68/0.72/0.78/0.82rem were all
     doing similar jobs. Each step here has one role. */
  --text-2xs: 0.68rem;    /* 11px — table headers, micro labels */
  --text-xs:  0.75rem;    /* 12px — help text, badges */
  --text-sm:  0.82rem;    /* 13px — controls, secondary UI */
  --text-base:0.9rem;     /* 14px — body, inputs */
  --text-md:  1rem;       /* 16px — page intro */
  --text-lg:  1.25rem;    /* 20px */
  --text-xl:  1.5rem;     /* 24px — card titles */
  --text-2xl: 2rem;       /* 32px */
  --text-3xl: 2.4rem;     /* 38px — page titles */
  --text-stat: 3rem;      /* 48px — stat tiles */
  --text-stat-hero: 4rem; /* 64px — hero stat */

  /* Motion. One duration and one curve used everywhere reads as deliberate; assorted timings read
     as accidental. The curve is fast-out, slow-in so movement settles rather than stops dead. */
  --ease: cubic-bezier(0.2, 0, 0, 1);
  --dur: 160ms;
  --dur-slow: 240ms;
  /* A third step for deliberate, watchable movement rather than acknowledgement of an action.
     240ms is enough to avoid a jump but still reads as a state flip; a large surface changing
     colour wants long enough to be seen as a transition. Only for hover treatments that are
     meant to be noticed — a button press must never sit here. */
  --dur-deliberate: 420ms;

  /* Table rhythm: row height is a decision, not a by-product of padding. */
  --table-row-h: 56px;

  --helion-measure: 58ch;   /* ~70 rendered characters — ch is the width of "0", so it overshoots */
  /* Sized so the content fills a 16" MacBook Pro exactly and caps beyond it. At that machine's
     1728pt logical width, minus the 104px collapsed rail and a 56px gutter each side, 1512 is
     what is left — so nothing is wasted there and wider displays get a cap rather than a line
     of text running the width of a 27" monitor. It was 1400, which left 136px of dead space on
     the right of a 16" screen. Raise it only with a screen in front of you: past roughly this
     width a full-width table row is harder to read across, not easier. */
  --helion-content-max: 1512px;
  /* The bleeding pill crosses both the navy rail and the cream page, so it must be OPAQUE —
     a translucent fill composites to two different colours either side of the edge. */
  --helion-nav-pill: #d8dee7;
  --helion-nav-pill-fg: #041324;
  /* Corner scale. Outer surfaces must stay rounder than what sits inside them, or a field near a
     card's corner reads as bulging out of it — so these three move together, never one alone. */
  --helion-radius: 10px;
  --helion-radius-sm: 8px;
  --helion-input-radius: 6px;
  /* Recessed field tones — darker than --helion-card-bg, so fields read as inset within a card.
     Focus lifts toward the card without reaching it: stopping short keeps the well visible, so an
     active field stays a distinct shape rather than dissolving into the card behind it. */
  --helion-input-bg: #e2e7ec;
  --helion-input-bg-hover: #dce1e8;
  --helion-input-bg-focus: #e8edf2;
  --helion-input-min-height: 3rem;
  /* A rich text body is somewhere to write paragraphs, not a line. Its own token rather than a
     spacing step, the same way --helion-input-min-height is. */
  --helion-richtext-min-height: 13rem;
  /* Field padding lives in tokens so the focus bar can align to the text rather than the box. */
  --helion-input-pad-x: 1rem;
  --helion-input-pad-y: 0.85rem;

  /* Ground — warm neutral scale, every grey derived from these two tones */
  /* Cool neutral scale, hue 254° — biased toward the navy rail (251.5°) rather than an
     arbitrary blue-grey, so the ground reads as chosen. Derived from the warm scale that
     preceded it by preserving each token's OKLCH lightness exactly and rotating hue only,
     which is why every contrast ratio and ΔE below survived the change to within 0.2. */
  --helion-bg: #eaecf0;
  --helion-card-bg: #f3f5f7;
  --helion-tint-bg: #dde3ea;
  --helion-border: #d8dee7;
  --helion-fg: #191b1f;
  --helion-muted: #6a7078;
  /* Muted ink for text sitting on the page ground rather than on a card. --helion-muted was
     measured against the card (4.57:1) and drops to 4.23:1 on the darker page, under AA — the
     same "don't derive one ground from another" trap as the stat wash. Darkened to clear it at
     4.83:1 while staying on the cool neutral axis. */
  --helion-muted-on-page: #61676f;
  /* Unfilled progress track. Sits on the page ground, not a card, so it cannot borrow
     --helion-border or --helion-tint-bg: both are within ~ΔE 2 of the page and vanish against
     it. Darker than either, while staying quiet enough that the filled gradient is what the
     eye goes to. */
  --helion-track: #cdd4de;
  --helion-heading: #041324;   /* brand ink navy — headings, matching the sidebar */
  --helion-auth-card-width: 500px;

  /* Nav (sidebar) — brand ink navy */
  --helion-nav: #041324;
  --helion-nav-raised: rgba(255, 255, 255, 0.10);
  --helion-nav-border: rgba(255, 255, 255, 0.10);
  --helion-nav-fg: #fff;
  --helion-nav-muted: rgba(255, 255, 255, 0.62);

  /* Accent — flat brand blue. Was a blue -> cyan gradient; flattened once the entity tones
     arrived, because everything else carrying colour is now flat and the gradient's two homes
     (the stat hero, the linked-tile hover) had both been replaced by then. It was the only
     gradient left, which read as a leftover rather than a decision.

     Still expressed as a gradient function rather than a bare colour: five of its ~19 usages are
     `background-image`, where a plain colour is invalid, and one composites with the select
     chevron. A single-stop gradient renders flat and keeps every call site unchanged.

     #0ea5e9 rather than the cyan end: --helion-on-accent navy measures 6.74 on it, where the
     logo cyan #02dafd would force 11.08 navy / 1.69 white and read almost white itself. */
  --helion-accent: #0ea5e9;
  --helion-accent-strong: #0284c7;
  --helion-accent-grad: linear-gradient(var(--helion-accent), var(--helion-accent));
  /* Soft accent ring for "this is the live one" — currently the halo on the active step dot.
     Alpha rather than a solid tint so it works over either ground. Defined once: the accent
     gradient is not redefined per theme, so its halo is not either. */
  --helion-accent-halo: rgba(14, 165, 233, 0.22);
  /* Was the horizontal twin of the gradient, for marks that grow left-to-right — the field focus
     bar, the meter fill. Flat now for the same reason, and kept as a separate token because those
     call sites are `background-image` and read as a distinct job from the block fills. */
  --helion-accent-grad-x: linear-gradient(var(--helion-accent), var(--helion-accent));
  --helion-accent-bg: #e4f4fc;
  /* Ink for anything sitting ON the accent gradient. Deliberately NOT overridden in dark: the
     gradient is bright in both themes, and white on it measures 2.77:1 at the blue end and
     1.69:1 at the cyan end — below AA even for large text. Navy gives 6.74 and 11.08. */
  --helion-on-accent: #041324;

  /* Entity tones — the colour a stat tile carries on its edge bar and icon chip.
     ────────────────────────────────────────────────────────────────────────────
     COLOUR FOLLOWS THE ENTITY, NOT THE POSITION. Jobs are blue on every page they
     appear on. Assigning by grid slot instead means the same figure changes colour
     from page to page, which is worse than no colour at all.

     Deliberately NO red and NO green: both are spoken for by the status chips
     (success, attention, rejected), and a tile is an identity, never a verdict.

     These are brighter than --chart-1…6 on purpose, and are NOT interchangeable
     with them. A chart series is identified by its colour alone, so it needs the
     stricter any-two-series separation that palette was validated for. A tile always
     carries a text label and its own icon, so its colour is reinforcement — which is
     what buys the extra brightness. If a mark ever has to be identified by colour
     with no label, use --chart-1…6, not these.

     Measured on the light card: bars land at ΔE 20.5–33.0, where the accent tint that
     was kept measured 8.5 and the wash rejected as invisible measured 2.7. Contrast
     ratio is the wrong metric here and says 1.48 for the gold — it only sees lightness,
     and these are chromatic marks on a near-neutral ground.

     JOBS IS DELIBERATELY NOT THE ACCENT BLUE. It was #00a3e0, which measured ΔE 1.4 from
     --helion-accent — the same colour. That was survivable only while the accent was a gradient
     and told apart by its form; flattening the accent left two identical blues meaning
     "interactive" and "about jobs" on the same page. The accent is brand-fixed, so jobs moved.
     A deep royal blue keeps jobs intuitively blue and separates by lightness rather than hue:
     ΔE 22.5 from the accent and 24.9 from the nearest other tone.

     The wheel is genuinely full here. With red and green reserved for status and five tones
     already placed, a search of every in-gamut hue found the best-separated candidates were all
     green, red or olive — all banned. Separating by lightness was the way out. Bear that in mind
     before adding a seventh tone: there is not much room left. */
  --helion-tone-jobs: #1d4ed8;
  --helion-tone-applications: #ff8a3d;
  --helion-tone-candidates: #00c2b2;
  --helion-tone-events: #b57bff;
  --helion-tone-feeds: #ffc233;
  --helion-tone-platform: #ff6fae;
  /* Ink for the glyph sitting ON a tone chip. Per tone, not one value, because the tones are no
     longer all light: navy measures 6.44–11.58 on the five bright ones and only 2.79 on the deep
     jobs blue, where white reaches 6.70. Neither ink follows the theme — the chips are the same
     colour in both, so their contrast partner cannot flip. */
  --helion-on-tone: #041324;
  --helion-on-tone-light: #ffffff;
  /* The hero is one deep navy rather than the accent gradient, so the bright tones on the
     plain tiles are the page's colour and the headline is its anchor. Lighter than the
     sidebar rail (ΔE 13.3) so the two do not read as one shape, and clear of the dark card
     (ΔE 9.5) so it still reads as a raised surface in dark. White on it measures 13.1. */
  --helion-hero-bg: #143156;
  --helion-on-hero: #ffffff;
  /* Supporting text on the hero. An ALPHA COLOUR, not `opacity` on the element: opacity dims
     every descendant and cannot be undone by one, so with it on .helion-stat-label the hover
     CTA nested inside could not reach full strength no matter what colour it asked for. Same
     reasoning as --helion-nav-muted on the sidebar. */
  --helion-on-hero-muted: rgba(255, 255, 255, 0.78);

  /* Toast inverts its surroundings so the system is visibly speaking rather than the page.
     Inversion is the RULE, not the colour: in dark mode --helion-nav (#121a24) sits almost on
     top of the card, so a navy toast would read as just another card and lose the whole idea.
     The dark theme therefore flips to a light toast. */
  --helion-toast-bg: #041324;
  --helion-toast-fg: #ffffff;
  --helion-toast-close-bg: rgba(255, 255, 255, 0.14);

  /* Semantic — separate from the accent, same meaning everywhere.
     Two rules keep these feeling part of Meridian rather than stickers dropped on top:
     every tint carries the ground's warmth so it sits on the cream page, and all four tints
     share a lightness while all four inks share a darkness, so no one state shouts louder
     than another. `info` is deliberately in the brand blue family — a second, unrelated blue
     next to the accent reads as an accident. */
  /* Tints are pulled toward the ground's warm cast and down near its saturation. The ground sits
     at hue 40 / sat 15; the previous tints ran sat 36-76 and only one shared the warm axis, which
     is what made them read as generic semantic colours dropped onto Meridian rather than part of
     it. Inks are unchanged, and every pair still clears AA. */
  --helion-success: #0a6a4f;
  --helion-success-bg: #e3ede8;
  --helion-warning: #8a5a10;
  --helion-warning-bg: #ebe4d5;
  --helion-info: #4a3fb0;
  --helion-info-bg: #e8e7ef;
  --helion-error: #b03a28;
  --helion-error-bg: #eee5e2;

  /* Status chips — the "Signal" scale. Solid fills for at-a-glance state in dense tables, where
     tints are too quiet to scan. Same four hues as the tinted scale above, so flashes and chips
     read as one system. Violet carries `info` deliberately: a chip in the accent's own blue would
     look like a brand element rather than a status.
     Amber is the one chip that takes dark text — white on amber cannot reach AA at any usable
     saturation. Neutral stays a quiet tint: chips that merely describe configuration should not
     compete with the ones that actually signal something. */
  --helion-chip-neutral: #dde3ea;   --helion-chip-neutral-fg: #4d5359;

  /* Quiet interactive controls sit RAISED — lighter than the card, where fields sit darker than it.
     Tone therefore encodes interactivity: light means pressable, dark means fillable. Before this,
     --helion-chip-neutral (#e6e2d9) and --helion-input-bg (#e9e6df) were three units apart, so a
     button and a text field were indistinguishable. Non-interactive badges keep the tint, which is
     what separates a label like "Follow-up" from a toggle like "Optional". */
  --helion-control-bg: #fbfcfd;
  --helion-control-bg-hover: #ebeff4;
  /* Hairline so a quiet control still reads as raised on a card, which is nearly as light as it.
     Buttons are outlined, fields are not — a second, redundant signal beyond tone alone. */
  --helion-control-edge: #d8dee7;
  --helion-chip-info: #6355e0;      --helion-chip-info-fg: #fff;
  --helion-chip-success: #0a7a5a;   --helion-chip-success-fg: #fff;
  --helion-chip-attention: #d1402d; --helion-chip-attention-fg: #fff;
  --helion-chip-warning: #e0a020;   --helion-chip-warning-fg: #3a2a05;

  /* Three more, added so a pipeline with eight states can give each its own colour rather than
     making several share one. Same rules as the four above: measured into the L* 45–49 band so no
     state shouts louder than another, and past 4.5:1 against their own foreground.

     Slate is deliberately light with dark text, the way warning is. At the same lightness as teal
     it measured deltaE 2.5 under deuteranopia — indistinguishable, the olive/crimson mistake over
     again. Two blue-ish chips cannot be separated by hue on the red-green axis, so this pair is
     separated by lightness instead: 20.0 under deuteranopia, 16.2 under protanopia. Do not darken
     slate back into the band without re-running that check. */
  --helion-chip-teal: #11818e;      --helion-chip-teal-fg: #fff;
  --helion-chip-slate: #93a3ba;     --helion-chip-slate-fg: #1e2937;
  --helion-chip-rose: #c23a6d;      --helion-chip-rose-fg: #fff;

  /* Stat tile corner wash. Deliberately a different gradient per theme, chosen and measured on its
     own card rather than derived from the other — the two grounds are not symmetrical.

     Light sits at L* 96, so there is almost nowhere lighter to go: even pure white only reaches
     deltaE 3.9 against the card. This buys its visibility from area rather than brightness — a
     wider reach held longer before it falls off — and warms the corner slightly so it reads as
     light rather than as a blown-out patch. Peak measures deltaE 3.4.

     Dark sits at L* 12 with plenty of headroom above it, so the plain raised tone is enough:
     deltaE 5.2. Carrying that same value into light mode is what produced an invisible wash —
     it measured 2.7 there, under the ~3 floor for two surfaces being tellable apart. */
  --helion-stat-wash: radial-gradient(150% 130% at 100% 100%, #fffdf8 0%, rgba(255, 253, 248, 0.55) 30%, transparent 82%);
  /* The disc behind a linked tile's icon on hover. White in BOTH themes on purpose: the hover
     ground is --helion-accent-grad, which is not redefined per theme, so the correct contrast
     partner does not flip either. */

  /* --- Charts -------------------------------------------------------------
     Categorical series colours. Assign in FIXED ORDER and never cycle — colour
     follows the entity, not its rank, so a filter that drops a series must not
     repaint the survivors. A 7th series folds into "Other" or becomes small
     multiples; it is never a generated hue.

     These are deliberately NOT the semantic/chip colours. If green means
     success everywhere else, a green series implies goodness. Status stays
     reserved and always ships with a label, never colour alone.

     Validated, not eyeballed — six checks against the card surface, in both
     themes: lightness band, chroma floor, colourblind separation of adjacent
     pairs, normal-vision separation, and 3:1 contrast. Earlier candidates
     failed on pairs that looked fine to me: olive/crimson measured ΔE 2.6
     under deuteranopia. Re-run the validator before changing any value. */
  --chart-1: #0072b2;   /* blue    */
  --chart-2: #c2410c;   /* orange  */
  --chart-3: #00806a;   /* teal    */
  --chart-4: #7c3aed;   /* violet  */
  --chart-5: #b87d00;   /* gold    */
  --chart-6: #a8547f;   /* mauve   */

  /* Sequential = ONE hue, light to dark, for magnitude. Never a rainbow. */
  --chart-seq-1: #dceefb;
  --chart-seq-2: #a8d5f2;
  --chart-seq-3: #63b0e0;
  --chart-seq-4: #2b8fc4;
  --chart-seq-5: #0072b2;

  /* Diverging = two poles + a NEUTRAL grey midpoint. Never a hue at the middle. */
  --chart-div-low: #0072b2;
  --chart-div-mid: #d9d5cc;
  --chart-div-high: #c2410c;

  /* Structure recedes: grid and axes must never compete with the data. */
  --chart-grid: var(--helion-border);
  --chart-axis: var(--helion-muted);
  --chart-track: var(--helion-tint-bg);   /* unfilled part of meters and donuts */
  --chart-muted: #c9c4b8;                 /* de-emphasised bars in a one-accent chart */

  --helion-select-chevron: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%23746f66' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
}


/* --- Dark theme -------------------------------------------------------------
   Applied by adding .helion-dark to <html>. The class is set before first paint
   by an inline script in the layout, so there is no flash of the wrong theme.
   Only token VALUES change here — no component rule is redefined. That is the
   payoff for building on tokens: the whole theme is this one block.

   The scale keeps its light-mode meaning, so every rule still holds:
     control (lightest, raised) > card > sidebar > page (darkest) > field (recessed)
   Headings drop the brand navy — at this size on a dark ground it would vanish;
   they take the brightest ink instead. */
html.helion-dark {
  color-scheme: dark;   /* native scrollbars, colour picker and date UI follow */

  --helion-bg: #0a0e13;
  --helion-card-bg: #151e29;
  --helion-tint-bg: #1e2733;
  --helion-border: #26303c;
  --helion-fg: #e3e6eb;
  --helion-muted: #9aa3ad;
  /* Dark's page ground has headroom the light one doesn't: muted already measures 7.57:1 there,
     so this deliberately stays equal rather than being darkened to match light's adjustment. */
  --helion-muted-on-page: #9aa3ad;
  --helion-track: #2b3542;   /* see the light block — measured against the dark page ground */
  --helion-heading: #f0f2f6;

  --helion-input-bg: #0f1620;
  --helion-input-bg-hover: #0c121b;
  --helion-input-bg-focus: #1a2432;

  --helion-control-bg: #1e2836;
  --helion-control-bg-hover: #26313f;
  --helion-control-edge: #2f3a49;

  /* Sidebar lifts off the page rather than merging into it. */
  --helion-nav: #121a24;
  --helion-nav-raised: rgba(255, 255, 255, 0.08);
  --helion-nav-border: rgba(255, 255, 255, 0.08);
  --helion-nav-muted: rgba(255, 255, 255, 0.55);
  /* The bleeding pill still has to be opaque and read as raised over BOTH the
     sidebar and the page — so it is a mid tone here, not the light one. */
  --helion-nav-pill: #2f3d4f;
  --helion-nav-pill-fg: #f0f2f6;

  --helion-accent-strong: #38bdf8;   /* links need lifting on a dark ground */
  --helion-accent-bg: #10293a;

  --helion-success: #7fd3b0;  --helion-success-bg: #10281f;
  --helion-warning: #e3b45f;  --helion-warning-bg: #2b2113;
  --helion-info:    #a99cf5;  --helion-info-bg:    #1e1b33;
  --helion-error:   #f0917f;  --helion-error-bg:   #2e1815;

  --helion-chip-neutral: #26303c;  --helion-chip-neutral-fg: #b9c1cb;

  /* The raised control tone is enough here — a dark card leaves room above it. deltaE 5.2. */
  --helion-stat-wash: radial-gradient(130% 110% at 100% 100%, var(--helion-control-bg) 0%, transparent 62%);
  --helion-toast-bg: #f0f2f6;
  --helion-toast-fg: #191b1f;
  --helion-toast-close-bg: rgba(4, 19, 36, 0.10);


  /* Dark chart steps are SELECTED, not an automatic flip — re-validated against
     the dark card surface. Only the violet needed lifting; at #7c3aed it fell to
     2.95:1 on #151e29. */
  --chart-4: #8b5cf6;
  --chart-seq-1: #10293a;
  --chart-seq-2: #17456a;
  --chart-seq-3: #1f6796;
  --chart-seq-4: #2b8fc4;
  --chart-seq-5: #4aa8e0;
  --chart-div-mid: #3a4553;
  --chart-muted: #33404f;

  /* Chevron is baked into a data: URI, so the stroke colour needs its own value. */
  --helion-select-chevron: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%239aa3ad' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
}
/* The auth wordmark is a dark SVG for the light card; swap to the light one. */
html.helion-dark .helion-logo-on-light { display: none; }
html:not(.helion-dark) .helion-logo-on-dark { display: none; }

html { --helion-sidebar-current: var(--helion-sidebar-rail); }
html.helion-sidebar-expanded { --helion-sidebar-current: var(--helion-sidebar-width); }

body {
  font-family: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 14px; line-height: 1.5; color: var(--helion-fg);
}

@media (prefers-reduced-motion: no-preference) {
  .helion-sidebar-brand { transition: padding-left var(--dur-slow) var(--ease); }
  .helion-sidebar, .helion-header, .helion-main, .helion-nav-label, .helion-logo-full { transition: width var(--dur) var(--ease), left var(--dur) var(--ease), margin-left var(--dur) var(--ease), opacity var(--dur) var(--ease), max-width var(--dur) var(--ease); }
}

h1, h2, h3, .helion-auth-title, .helion-card-title, .helion-page-header h2 {
  font-family: 'Archivo', -apple-system, sans-serif;
  font-weight: 700;
  letter-spacing: -0.005em;
  text-wrap: balance;
  /* Brand ink navy rather than near-black — same tone as the sidebar, so headings tie back to it. */
  color: var(--helion-heading);
}

/* --- Auth layout --- */

.helion-auth { background: var(--helion-bg); min-height: 100vh; display: flex; align-items: center; justify-content: center; }
/* Container is the card width plus its own gutter, so the card itself lands on
   --helion-auth-card-width on desktop and still shrinks cleanly on small screens. */
.helion-auth-container { width: 100%; max-width: calc(var(--helion-auth-card-width) + 2rem); padding: var(--space-4); }
.helion-auth-card { background: var(--helion-card-bg); border: none; border-radius: var(--helion-radius); padding: var(--space-6); }
.helion-auth-logo { margin-bottom: var(--space-5); display: flex; justify-content: center; }
.helion-auth-logo img { height: 26px; width: auto; }
.helion-auth-title { font-size: var(--text-lg); margin-bottom: var(--space-2); }
.helion-auth-subtitle { color: var(--helion-muted); font-size: var(--text-sm); margin-bottom: var(--space-4); }
.helion-auth-links { margin-top: var(--space-4); text-align: center; }

/* --- App layout --- */
/* Sidebar spans full height on the left; header covers only the content area beside it. */

.helion-app { background: var(--helion-bg); min-height: 100vh; }

.helion-sidebar {
  position: fixed; top: 0; left: 0; bottom: 0;
  width: var(--helion-sidebar-current); background: var(--helion-nav);
  padding: 0 0 var(--space-4); z-index: 110;
  /* MUST stay visible on both axes: the active/hover nav pill deliberately bleeds out past the
     sidebar's right edge onto the page background. Note `overflow-y: auto` would force
     `overflow-x` to compute as `auto` too (per spec, a non-visible axis coerces the other),
     which silently clips the bleed — that is exactly what broke this before. */
  overflow: visible;
  display: flex; flex-direction: column; gap: 0;
}

/* The brand fills the same vertical band as the header, so the sidebar's content below it starts
   on the same line as the page content — the avatar ends up level with the page title rather than
   crowding the wordmark. */
.helion-sidebar-brand {
  display: flex; align-items: center; height: var(--helion-header-height); flex: none;
  /* Collapsed, the mark is centred on the rail. Expanded, it slides left to sit on the same
     vertical line as the company avatar below it — otherwise it reads as shifted right and the
     column has no left edge. Both positions are derived, not eyeballed: the expanded inset is
     exactly the switcher's own padding plus the toggle's, so it tracks them if either changes. */
  padding-left: calc((var(--helion-sidebar-rail) - 24px) / 2);
  padding-right: var(--space-4);
}
html.helion-sidebar-expanded .helion-sidebar-brand {
  padding-left: calc(var(--space-3) + var(--space-2));
}
/* No fixed slot: the brand's padding places the mark, so it can animate between the two. */
.helion-logo-mark-slot { display: flex; align-items: center; flex: none; }
.helion-logo-mark { height: 24px; width: auto; }
.helion-logo-full { height: 18px; width: auto; opacity: 0; max-width: 0; margin-left: 0; overflow: hidden; }
/* margin-left:auto pushes the wordmark to the far right of the expanded sidebar, rather than
   letting it sit immediately beside the mark and float in the middle. */
html.helion-sidebar-expanded .helion-logo-full { opacity: 1; max-width: 140px; margin-left: auto; }

.helion-header {
  position: fixed; top: 0; left: var(--helion-sidebar-current); right: 0; height: var(--helion-header-height);
  background: var(--helion-bg); color: var(--helion-fg);
  display: flex; align-items: center; justify-content: space-between; padding: 0 var(--space-5);
  z-index: 100;
}
.helion-header-left { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
/* The sidebar carries the logo on desktop; below the breakpoint it is off-canvas, so the header
   picks up the wordmark to keep the app branded. */
.helion-header-brand { display: none; align-items: center; }
.helion-header-brand img { height: 17px; width: auto; }
.helion-header-center { color: var(--helion-muted); font-size: var(--text-sm); }
.helion-header-right { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); }

.helion-icon-btn {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 999px; background: none; cursor: pointer;
  color: var(--helion-muted); padding: 0;
  /* Resting border in the hover fill colour — gives the icons a defined footprint so they sit
     deliberately rather than floating, and the hover state fills in rather than appearing. */
  border: 1px solid var(--helion-tint-bg);
}
.helion-icon-btn:hover { background: var(--helion-tint-bg); color: var(--helion-fg); }
.helion-icon-btn[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute; top: 100%; right: 0; margin-top: 10px;
  background: var(--helion-nav); color: #fff; font-size: var(--text-xs); font-weight: 500; white-space: nowrap;
  padding: var(--space-2) var(--space-3); border-radius: 12px; opacity: 0; pointer-events: none; z-index: 400;
  transform: translateY(-2px); transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.helion-icon-btn:hover[data-tooltip]::after, .helion-icon-btn:focus-visible[data-tooltip]::after { opacity: 1; transform: translateY(0); }

.helion-sidebar-toggle {
  background: none; border: none; cursor: pointer; padding: 6px; border-radius: var(--helion-radius-sm);
  display: flex; flex-direction: column; gap: 3px;
}
.helion-sidebar-toggle:hover { background: var(--helion-tint-bg); }
.helion-sidebar-toggle span { display: block; width: 18px; height: 2px; border-radius: 2px; background: var(--helion-fg); }

.helion-nav { list-style: none; display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-6); }
.helion-nav-item { position: relative; padding: 0 var(--space-3); }
@media (prefers-reduced-motion: no-preference) {
  .helion-nav-link { transition: background var(--dur) var(--ease), color var(--dur) var(--ease), width var(--dur) var(--ease), padding-right var(--dur) var(--ease); }
  .helion-input, .helion-select { transition: background-color var(--dur) var(--ease), background-size var(--dur-slow) var(--ease); }
  .helion-btn { transition: transform var(--dur) var(--ease), filter var(--dur) var(--ease); }
  .helion-btn-small, .helion-btn-icon, .helion-btn-toggle, .helion-company-toggle, .helion-link-btn,
  .helion-badge, .helion-icon-btn, .helion-table tbody tr td
    { transition: background var(--dur) var(--ease), color var(--dur) var(--ease), transform var(--dur) var(--ease); }
  .helion-checkbox input, .helion-radio input { transition: background var(--dur) var(--ease); }
  .helion-checkbox input::before, .helion-radio input::before { transition: transform var(--dur) var(--ease); }
}

.helion-nav-link {
  display: flex; align-items: center; gap: 0; width: 100%; padding: var(--space-4);
  border-radius: 999px; color: var(--helion-nav-muted); text-decoration: none; font-size: var(--text-sm); font-weight: 500;
}
html.helion-sidebar-expanded .helion-nav-link { gap: var(--space-3); }
html:not(.helion-sidebar-expanded) .helion-nav-link { justify-content: center; }
/* The icon wrapper is otherwise a plain inline box, so its SVG aligns to the text baseline and the
   line box reserves descender space below it — leaving the icon sitting visibly above the pill's
   centre. Making the wrapper a flex container drops baseline alignment so it centres properly. */
.helion-nav-icon { display: inline-flex; align-items: center; justify-content: center; flex: none; }
.helion-nav-svg { flex: none; display: block; }

/* Icons sitting beside a label. align-items: center centres the icon on the text's *box*, which
   includes the descender space below the baseline — so the icon lands above the optical centre of
   the letters and reads as floating high. Most button labels have no descender at all, which makes
   the mismatch obvious. A 1px nudge puts it on the cap-height centre instead.
   14px is the size for an icon next to text; 18px and up is for standalone and nav use. */
.helion-btn > .helion-nav-svg,
.helion-btn-small > .helion-nav-svg,
.helion-menu-item > .helion-nav-svg { margin-top: 1px; }
/* Hover stays inside the rail — subtle, translucent, no bleed. */
.helion-nav-link:hover { background: var(--helion-nav-raised); color: var(--helion-nav-fg); }

/* Active bleeds OUT: keeps the full capsule shape and its resting left gutter, but overhangs the
   sidebar's right edge onto the page background by --helion-nav-bleed. Adding the item's own
   0.7rem gutter back means the overhang equals the token exactly. The matching padding-right
   keeps the icon optically centred over the rail instead of drifting right with the extra width.
   Requires `.helion-sidebar { overflow: visible }` — see the note there. */
.helion-nav-item.active > .helion-nav-link {
  background: var(--helion-nav-pill); color: var(--helion-nav-pill-fg);
  width: calc(100% + var(--space-3) + var(--helion-nav-bleed));
  padding-right: calc(var(--space-4) + var(--space-3) + var(--helion-nav-bleed));
}
/* Flyout children sit in their own panel off to the side — they must not bleed. */
.helion-nav-children .helion-nav-item.active > .helion-nav-link {
  width: 100%; padding-right: var(--space-3);
  background: var(--helion-nav-raised); color: var(--helion-nav-fg);
}
.helion-nav-label { opacity: 0; max-width: 0; overflow: hidden; white-space: nowrap; }
html.helion-sidebar-expanded .helion-nav-label { opacity: 1; max-width: 140px; }

/* Tooltip for simple (leaf) rail icons */
html:not(.helion-sidebar-expanded) .helion-nav > .helion-nav-item:not(.helion-nav-group) [data-tooltip] { position: relative; }
html:not(.helion-sidebar-expanded) .helion-nav > .helion-nav-item:not(.helion-nav-group) [data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute; top: 50%; left: 100%; margin-left: 12px; transform: translateY(-50%) translateX(-4px);
  background: var(--helion-nav); color: #fff; font-size: var(--text-xs); font-weight: 500; white-space: nowrap;
  padding: var(--space-2) var(--space-3); border-radius: 12px; opacity: 0; pointer-events: none; z-index: 300;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
html:not(.helion-sidebar-expanded) .helion-nav > .helion-nav-item:hover [data-tooltip]::after { opacity: 1; transform: translateY(-50%) translateX(0); }

/* Children — inline list when expanded, hover flyout when collapsed (so they're always reachable) */
/* Column gap keeps sub-item pills from colliding on hover — applies to both the expanded
   inline list and the collapsed flyout, which share this element. */
.helion-nav-children { list-style: none; display: flex; flex-direction: column; gap: var(--space-1); }
html.helion-sidebar-expanded .helion-nav-group:not(.open) .helion-nav-children { display: none; }
html.helion-sidebar-expanded .helion-nav-children { padding-top: var(--space-1); }
/* Tighter vertical padding than top-level items — sub-items should read as lighter, not chunky. */
html.helion-sidebar-expanded .helion-nav-children .helion-nav-link { padding: var(--space-2) var(--space-4) var(--space-2) 2.3rem; font-size: var(--text-sm); }

html:not(.helion-sidebar-expanded) .helion-nav-children {
  position: absolute; left: calc(100% + 12px); top: 0; min-width: 180px;
  background: var(--helion-nav); border-radius: var(--helion-radius); padding: var(--space-2);
  opacity: 0; pointer-events: none; transform: translateX(-6px); z-index: 300;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
/* Invisible bridge across the 12px gap between the rail and the flyout. Without it the cursor
   leaves .helion-nav-group before reaching the flyout, :hover drops, and the menu vanishes
   mid-reach. Inert at rest because the flyout is pointer-events:none until hovered. */
html:not(.helion-sidebar-expanded) .helion-nav-children::before {
  content: ''; position: absolute; top: 0; bottom: 0; left: -20px; width: 20px;
}
html:not(.helion-sidebar-expanded) .helion-nav-group:hover .helion-nav-children,
html:not(.helion-sidebar-expanded) .helion-nav-group:focus-within .helion-nav-children { opacity: 1; pointer-events: auto; transform: translateX(0); }
html:not(.helion-sidebar-expanded) .helion-nav-children .helion-nav-item { padding: 0; }
html:not(.helion-sidebar-expanded) .helion-nav-children .helion-nav-link { justify-content: flex-start; padding: var(--space-2) var(--space-3); }
html:not(.helion-sidebar-expanded) .helion-nav-children .helion-nav-label { opacity: 1; max-width: none; }
.helion-nav-flyout-title { display: none; }
html:not(.helion-sidebar-expanded) .helion-nav-flyout-title { display: block; padding: var(--space-2) var(--space-3) var(--space-2); font-size: var(--text-2xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--helion-nav-muted); }

.helion-main {
  margin-left: var(--helion-sidebar-current); margin-top: var(--helion-header-height);
  max-width: calc(var(--helion-content-max) + (var(--helion-content-gutter) * 2));
  /* The gutter is on BOTH sides now. It exists on the left because the active nav pill bleeds
     --helion-nav-bleed into this area and content needs clearance beyond normal page padding;
     matching it on the right is what stops a full-width page sitting tight against the window
     edge. The right side used to be --space-6, which read as off-centre once the content filled
     the screen. */
  padding: var(--space-5) var(--helion-content-gutter) var(--space-6) var(--helion-content-gutter);
}

/* --- Shared components --- */

/* space-5 between groups against space-2 inside them — a 3:1 ratio. At the old 16px the gap
   between two groups was only twice the gap between a label and its own control, which is not
   enough separation to read as grouping: the eye saw an evenly spaced stack of small grey lines
   rather than four units of label + field + note. The ratio is the point, not the number. */
.helion-field { position: relative; margin-bottom: var(--space-5); }
/* A label and the help text under it were both --helion-muted, and the help text was the LARGER
   of the two — the subordinate line outranking its own heading, which left every form reading as
   one undifferentiated grey block. The label takes the darker running-copy ink (7.1:1) so the two
   levels separate by weight AND colour, and help drops a step below it.

   Then a further step: matched at 12px they still read as one texture, because a weight and a
   grey are not much to tell two lines apart. The label takes --text-sm and the FULL ink, so the
   three levels of a form now differ on every axis available — size, weight and colour — rather
   than sharing two of three. Not accent blue: blue is spoken for by links, focus rings and role
   chips, and 118 blue labels would spend the accent on the most static text in the product. */
.helion-label { display: block; font-size: var(--text-sm); font-weight: 500; color: var(--helion-fg); margin-bottom: var(--space-2); }

/* Fields are RECESSED. Cards sit lighter than the page because lighter reads as raised; a field is
   somewhere you put something into, so it goes darker than its container. Same tone-on-tone logic
   as the rest of Meridian, inverted — which is what lets the borders go away entirely.
   `display: block` matters: textareas and selects are inline-block, so they'd otherwise carry a
   baseline descender gap and the focus bar would float below the field. */
.helion-input, .helion-select {
  display: block; width: 100%; padding: var(--helion-input-pad-y) var(--helion-input-pad-x);
  min-height: var(--helion-input-min-height);
  border: none; border-radius: var(--helion-input-radius);
  background-color: var(--helion-input-bg); color: var(--helion-fg);
  font-size: var(--text-base); font-family: inherit; line-height: 1.45;
}
textarea.helion-input { resize: vertical; min-height: 5rem; }
.helion-input::placeholder { color: var(--helion-muted); }
.helion-input:hover, .helion-select:hover { background-color: var(--helion-input-bg-hover); }
/* Focus lifts the field, stopping short of card tone so the well stays legible — no ring, no shadow. */
.helion-input:focus, .helion-select:focus { outline: none; background-color: var(--helion-input-bg-focus); }
.helion-input:disabled, .helion-select:disabled { opacity: 0.55; cursor: not-allowed; }

/* Native select: strip the OS chrome and supply our own chevron. Inline data: URI rather than an
   asset reference so Propshaft has no url() path to rewrite. */
.helion-select {
  /* padding-right clears the chevron, which is positioned in px — not a scale step. */
  appearance: none; -webkit-appearance: none; padding-right: 2.4rem; cursor: pointer;
}

/* Signature active state: the brand gradient sweeps across the base of the focused field.
   It lives on .helion-field because <input> and <select> can't carry pseudo-elements. */
/* The focus bar is a BACKGROUND of the control, not a positioned element on .helion-field.
   That's what lets it run across the very bottom while still being clipped by the field's corner
   radius — backgrounds honour border-radius, so the bar curves away with the corners instead of
   overhanging them or having to be inset away from the edge. It grows via background-size. */
.helion-input {
  background-image: var(--helion-accent-grad-x);
  background-repeat: no-repeat;
  background-position: left bottom;
  background-size: 0% 2px;
}
.helion-input:focus { background-size: 100% 2px; }
/* Select carries two layers: its chevron, then the focus bar underneath it. */
.helion-select {
  background-image: var(--helion-select-chevron), var(--helion-accent-grad-x);
  background-repeat: no-repeat, no-repeat;
  background-position: right 0.95rem center, left bottom;
  background-size: auto, 0% 2px;
}
.helion-select:focus { background-size: auto, 100% 2px; }
.helion-field:focus-within::after { transform: scaleX(1); }

/* Rails wraps the label+input of an invalid field in this div; display:contents keeps it out of
   the layout so .helion-field's positioning still applies. */
.field_with_errors { display: contents; }

/* Combobox — a dropdown we draw ourselves, because a native one cannot be styled. No CSS reaches
   the popup list of a <select> or <datalist> in any browser, so those lists arrive as OS chrome
   in the middle of a Meridian form however carefully the closed control is styled.

   The input keeps .helion-input, so the recessed fill and the gradient focus sweep are the same
   as every other field: only the list is ours. */
.helion-combobox { position: relative; }
.helion-combobox-control { position: relative; }
/* The same chevron as .helion-select, so the two read as one control while both exist. */
.helion-combobox-input { padding-right: var(--space-8); }
/* 12x8 is the chevron's own size, and .helion-select paints it at that size from the same 0.95rem
   inset. Sizing the box to 1rem and letting it scale to contain made it a third too big and no
   longer the same mark as every native select on the page. */
.helion-combobox-caret {
  position: absolute; right: 0.95rem; top: 50%; transform: translateY(-50%);
  width: 12px; height: 8px; pointer-events: none;
  background: var(--helion-select-chevron) no-repeat center;
}

.helion-combobox-panel {
  position: absolute; top: calc(100% + var(--space-2)); left: 0; right: 0; z-index: 300;
  max-height: 280px; overflow-y: auto; padding: var(--space-2);
  background: var(--helion-card-bg); border-radius: var(--helion-radius-sm);
  /* Same reasoning as the overflow menu: this floats on the page ground, where card-on-page is
     about ΔE 3 — barely a boundary. The edge is what makes it a surface. */
  border: 1px solid var(--helion-border);
  display: flex; flex-direction: column; gap: 2px;
}
.helion-combobox-option {
  display: flex; align-items: baseline; gap: var(--space-4); width: 100%; text-align: left;
  background: none; border: none;
  padding: var(--space-3) var(--space-4); border-radius: var(--helion-radius-sm);
  font-size: var(--text-sm); font-family: inherit; color: var(--helion-fg); cursor: pointer;
}
/* An example value beside the name it belongs to. Truncated rather than wrapped: it is there to
   confirm you are picking the right field, not to be read in full — a description that wraps to
   three lines turns a scannable list into a wall. */
.helion-combobox-option-label { flex: none; }
.helion-combobox-option-hint {
  margin-left: auto; min-width: 0; flex: 0 1 auto;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--text-2xs); color: var(--helion-muted); text-align: right;
}
/* Keyboard and pointer share one highlight, so arrowing down looks the same as hovering —
   two separate treatments read as two different things happening.

   The accent tint, not --helion-tint-bg: that sits three units from --helion-input-bg, so a
   highlighted option read as another form field rather than as a selection. This is the same
   tint the company switcher marks its current company with. */
.helion-combobox-option.is-active { background: var(--helion-accent-bg); }
.helion-combobox-option.is-selected { color: var(--helion-accent-strong); font-weight: 600; }
.helion-combobox-empty { padding: var(--space-3) var(--space-4); font-size: var(--text-sm); color: var(--helion-muted); }
.field_with_errors .helion-input, .field_with_errors .helion-select { background-color: var(--helion-error-bg); }

.helion-btn {
  display: inline-flex; align-items: center; justify-content: center;
  /* An icon needs air before the label. Without a gap the two touch, which reads as a collision
     rather than a pair — .helion-btn-small has always had one, .helion-btn never did. */
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5); border: none; border-radius: 999px;
  font-size: var(--text-sm); font-family: inherit; font-weight: 600; cursor: pointer; text-decoration: none;
}
.helion-btn-primary { background: var(--helion-accent-grad); color: var(--helion-on-accent); }
.helion-btn-primary:hover { filter: brightness(1.06); }
.helion-btn:active { transform: translateY(1px); }
.helion-btn-primary:active { filter: brightness(0.95); }
.helion-btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; filter: none; }
/* Full-width is an auth-card concern, not a property of every primary button. */
.helion-auth-card .helion-btn-primary { width: 100%; }
.helion-btn:focus-visible, .helion-nav-link:focus-visible, .helion-sidebar-toggle:focus-visible,
.helion-icon-btn:focus-visible, .helion-link:focus-visible, .helion-btn-small:focus-visible,
.helion-btn-toggle:focus-visible, .helion-btn-icon:focus-visible, .helion-link-btn:focus-visible,
.helion-company-toggle:focus-visible, .helion-company-option:focus-visible,
.helion-checkbox input:focus-visible, .helion-radio input:focus-visible
  { outline: 2px solid var(--helion-accent); outline-offset: 2px; }

.helion-link { color: var(--helion-accent-strong); text-decoration: none; font-size: var(--text-sm); }
.helion-link:hover { text-decoration: underline; }

.helion-flash { padding: var(--space-2) var(--space-4); border-radius: var(--helion-radius-sm); margin-bottom: var(--space-4); font-size: var(--text-sm); }
.helion-flash-success { background: var(--helion-success-bg); color: var(--helion-success); }
.helion-flash-error { background: var(--helion-error-bg); color: var(--helion-error); }


/* --- Company switcher --- */

/* Scope selector at the top of the sidebar: everything in the nav below operates inside the
   selected company, so it sits above the nav rather than floating in the header. Collapses to a
   circular initial, since the rail is icon-only. */
.helion-company-switcher { position: relative; padding: 0 var(--space-3); flex: none; margin-top: 2.45rem; }
.helion-company-toggle {
  width: 100%; background: var(--helion-nav-raised); border: none; color: var(--helion-nav-fg);
  border-radius: 999px; padding: var(--space-2) var(--space-3) var(--space-2) var(--space-2); font-size: var(--text-sm);
  font-family: inherit; cursor: pointer; display: flex; align-items: center; gap: var(--space-2);
  text-align: left;
}
.helion-company-toggle:hover { background: rgba(255, 255, 255, 0.16); }
.helion-company-static { cursor: default; }
.helion-company-static:hover { background: var(--helion-nav-raised); }
.helion-company-avatar {
  width: 32px; height: 32px; border-radius: 999px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  /* A company's brand colour when it has one, the accent when it does not. --brand is set
     inline per company by helion_brand_style; the fallbacks here are what every company
     without a brand keeps, so an unbranded company looks normal rather than broken.
     --brand-ink is computed from the fill's luminance in the helper, never stored, so a
     pale brand gets dark ink and a dark one gets white without anybody choosing. */
  background: var(--brand, var(--helion-accent-grad)); color: var(--brand-ink, var(--helion-on-accent));
  font-weight: 600; font-size: var(--text-sm); font-family: 'Archivo', sans-serif;
}
.helion-company-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* On the rail only the avatar survives; the toggle shrinks to it. */
html:not(.helion-sidebar-expanded) .helion-company-toggle { justify-content: center; padding: var(--space-2); gap: 0; }
html:not(.helion-sidebar-expanded) .helion-company-label,
html:not(.helion-sidebar-expanded) .helion-caret { display: none; }
.helion-caret { font-size: var(--text-2xs); color: var(--helion-nav-muted); flex: none; }
.helion-company-dropdown { position: absolute; top: 100%; left: 0.7rem; margin-top: 8px; background: var(--helion-card-bg); border: none; border-radius: var(--helion-radius-sm); min-width: 230px; max-height: 320px; overflow-y: auto; z-index: 300; padding: var(--space-2); display: flex; flex-direction: column; gap: var(--space-1); }
.helion-company-option-form { margin: 0; }
.helion-company-option { display: block; width: 100%; text-align: left; background: none; border: none; padding: var(--space-3) var(--space-4); border-radius: var(--helion-radius-sm); font-size: var(--text-sm); font-family: inherit; cursor: pointer; }
.helion-company-option:hover { background: var(--helion-tint-bg); }
/* Divides the "All companies" scope from the companies themselves. Translucent white rather than
   --helion-border: this panel sits on the navy rail, where the warm border token disappears. */
/* --helion-border, not a white alpha. The dropdown sits on --helion-card-bg, which is light,
   so white at 14% painted to rgb(245,246,248) against a rgb(243,245,247) fill — an RGB
   distance of 2.4, which is no line at all. A leftover from when this menu was dark. */
.helion-company-sep { height: 1px; background: var(--helion-border); margin: var(--space-2) var(--space-3); }
.helion-company-option.active { color: var(--helion-accent-strong); font-weight: 600; background: var(--helion-accent-bg); }
/* The one option that is an action rather than a scope — it navigates instead of switching, so it
   reads quieter than the companies above it and carries an icon to say it does something else.
   display: flex overrides the block above, which is for the <button> options. */
.helion-company-option-add { display: flex; align-items: center; gap: var(--space-2); color: var(--helion-muted); text-decoration: none; }
.helion-company-option-add:hover { color: var(--helion-fg); }
.helion-company-option-add > svg { width: 13px; height: 13px; flex: none; }
[x-cloak] { display: none; }

.helion-card { background: var(--helion-card-bg); border: none; border-radius: var(--helion-radius); padding: var(--space-6) var(--space-6); margin-bottom: var(--helion-card-gap); }
.helion-card-title { font-size: var(--text-xl); margin-bottom: var(--space-4); }
/* A running import, shown while it runs. The bar is the same gradient-on-track pairing as the
   step strip, so "something is progressing" looks the same wherever it appears. */
.helion-progress-card { border: 1px solid var(--helion-border); border-radius: var(--helion-radius); padding: var(--space-5) var(--space-6); margin-bottom: var(--helion-card-gap); }
.helion-progress-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-4); flex-wrap: wrap; }
.helion-progress-title { font-size: var(--text-sm); font-weight: 600; color: var(--helion-heading); display: flex; align-items: center; gap: var(--space-3); }
.helion-progress-count { font-size: var(--text-sm); color: var(--helion-muted-on-page); font-variant-numeric: tabular-nums; }
.helion-progress-track { height: 6px; border-radius: 999px; background: var(--helion-track); margin-top: var(--space-4); overflow: hidden; }
.helion-progress-fill { height: 100%; border-radius: 999px; background: var(--helion-accent-grad); }
.helion-progress-note { font-size: var(--text-2xs); color: var(--helion-muted-on-page); margin-top: var(--space-3); }
/* A pulsing dot, because a bar that has not moved for ten seconds looks stalled rather than
   working — an item can take a while when a model is writing its description. */
.helion-progress-dot { width: 8px; height: 8px; border-radius: 999px; background: var(--helion-accent); flex: none; }
@media (prefers-reduced-motion: no-preference) {
  .helion-progress-fill { transition: width var(--dur-deliberate) var(--ease); }
  .helion-progress-dot { animation: helion-pulse 1.6s var(--ease) infinite; }
}
@keyframes helion-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }

/* Job listing as cards rather than table rows. A table gives one line per job and no room for
   what the job actually is; every imported job carries an AI summary, and a card can show it.
   The trade-off is honest: fewer jobs on screen, and no column alignment to scan down — so the
   figures that are compared between jobs (salary, closing date) are pinned to the right edge
   where they still form a column.

   Not .helion-card: these are a list of records, and a row that responds to hover is the table's
   behaviour carried over, not a card's. */
.helion-job-list { display: flex; flex-direction: column; gap: var(--space-4); }
/* The card is two columns and a full-width action row, not a stack of rows.
   As a stack, the title row was as tall as whatever the figures column held — a logo over a
   three-line salary made it 103px for a 24px title, and the address landed 83px below the thing it
   describes. In columns the address sits directly under the title and the figures are free to be
   as tall as they need without pushing the text down. */
.helion-job {
  background: var(--helion-card-bg); border-radius: var(--helion-radius);
  padding: var(--space-5) var(--space-6);
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  /* --space-7 rather than --space-6: the summary runs the full width of its column now, so the two
     columns meet along their whole height rather than only where the title is. At 32px a long
     salary — the sentence some feeds put in the field — sat close enough to the summary to read as
     one wrapped block. */
  column-gap: var(--space-7); align-items: start;
}
.helion-job-main { grid-column: 1; grid-row: 1; min-width: 0; }
/* Ranged right so the figures line up down the list. min-width keeps the salary from being
   squeezed into a three-line stack by a long title beside it. */
.helion-job-aside {
  grid-column: 2; grid-row: 1;
  display: flex; flex-direction: column; align-items: flex-end; gap: var(--space-2);
  text-align: right; width: 300px;
}
/* The logo gets its own clearance rather than the whole column being loosened: the aside runs
   logo -> salary -> closing date, and widening the flex gap would push the date off the salary
   too, which belong together. 8px of gap plus 8px here reads as a break between a mark and a
   figure rather than three things spaced equally. */
.helion-job-aside > .helion-company-logo { margin-bottom: var(--space-2); }
.helion-job-when { font-size: var(--text-sm); color: var(--helion-muted); white-space: nowrap; }
.helion-job-actions { grid-column: 1 / -1; }
/* On a phone there is no room for two columns: the figures column will not shrink below its
   min-width, so the text column takes the squeeze and lands at 82px — three words a line. Stacked,
   the figures range left with the text rather than hugging an edge that is no longer there. */
@media (max-width: 640px) {
  .helion-job { grid-template-columns: 1fr; row-gap: var(--space-4); }
  .helion-job-main, .helion-job-aside { grid-column: 1; grid-row: auto; }
  .helion-job-aside { align-items: flex-start; text-align: left; width: auto; }
}
.helion-job-title { font-size: var(--text-md); font-weight: 600; text-decoration: none; color: var(--helion-heading); }
.helion-job-title:hover { text-decoration: underline; }
/* Salary is bold heading ink, not the semantic green a job board would use: green means success
   in Meridian, and a wage is a figure rather than a good outcome. */
/* Wrapping rather than nowrap: a salary is usually "£14.39 – £15.25 per hour" but a feed can put a
   whole sentence in the field. The old cap was a percentage of the title's flex row; in a column of
   its own that resolved against the column instead and broke "£14.39 – £15.25 per hour" over three
   lines. The column bounds the sentence case now, so the figure itself is uncapped. */
.helion-job-figure {
  font-weight: 600; color: var(--helion-heading); font-variant-numeric: tabular-nums;
  text-align: right; max-width: 100%;
}
.helion-job-where {
  margin-top: var(--space-1); font-size: var(--text-sm); color: var(--helion-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.helion-job-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-3); }
/* Uncapped. Capped to a measure, the summary stopped well short of the figures column and left a
   band of empty card between the two — the text crammed left, the figures crammed right, and a hole
   down the middle. The card is a fixed height per row regardless, so a longer line here costs
   nothing and closes the gap. */
.helion-job-summary {
  margin: var(--space-4) 0 0; font-size: var(--text-sm); color: var(--helion-fg);
}
.helion-job-actions { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-4); }

/* The filter bar. Wraps to as many rows as it needs rather than forcing every control onto one
   line — seven filters at a usable width do not fit, and shrinking them to fit makes each
   unreadable. */
/* --space-3, not --space-4. The fields are 3rem tall, so at 16px apart in a single column they
   read as separate blocks rather than one form; 12px keeps them a group. Only used on the jobs
   index, so this is not a shared-spacing change. */
.helion-filter-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--space-3); }
.helion-filter-actions { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; margin-top: var(--space-4); }
.helion-result-count { font-size: var(--text-sm); color: var(--helion-muted-on-page); margin: 0 0 var(--space-4); }

/* Pagination. Its own Kaminari theme rather than the Bootstrap default — see
   app/views/kaminari/helion. Pages are quiet control-tone pills; the current one takes the brand
   gradient, the same mark the active tab and the live step use. */
.helion-pagination { display: flex; align-items: center; justify-content: center; gap: var(--space-3); flex-wrap: wrap; margin-top: var(--space-5); }
.helion-pagination-pages { display: flex; align-items: center; gap: var(--space-1); flex-wrap: wrap; }
.helion-page {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-width: 34px; height: 34px; padding: 0 var(--space-3); border-radius: 999px;
  font-size: var(--text-sm); font-weight: 500; text-decoration: none;
  color: var(--helion-fg); background: var(--helion-control-bg);
  border: 1px solid var(--helion-control-edge);
}
.helion-page:hover { background: var(--helion-control-bg-hover); }
.helion-page.is-current {
  background: var(--helion-accent-grad); color: var(--helion-on-accent);
  border-color: transparent; font-weight: 600;
}
.helion-page-step { padding: 0 var(--space-4); }
/* The same chevron as the selects, turned. One mark for "there is more this way". */
.helion-page-caret {
  width: 12px; height: 8px; background: var(--helion-select-chevron) no-repeat center;
  transform: rotate(-90deg);
}
.helion-page-caret.is-prev { transform: rotate(90deg); }
.helion-page-gap { padding: 0 var(--space-2); color: var(--helion-muted-on-page); }

/* Back out of a detail page. Above the title, not among the page actions: it is navigation, and
   the header's actions are things you do to the record — the same separation the tab strips make.
   Quiet, because getting back should be findable without competing with the primary action. */
/* A company's logo, with an initial as the fallback.

   Sized by HEIGHT, with width free up to a maximum. Logos are not square — Brandon Trust's is
   642x311 — and a square box sized one into a 32x15 smear while a square logo got the whole 32x32.
   A fixed height is how a row of logos is normalised anywhere they appear together: every mark
   reads at the same optical weight whatever its aspect. object-fit: contain, never cover, because
   a logo cropped to fit is a damaged logo.

   The white tile is deliberate and is NOT themed. Logos arrive as whatever the company has: a JPEG
   cannot carry transparency, so it comes with its own white background, and a transparent PNG is
   usually drawn in dark ink for light backgrounds. Both are unreadable or ugly on a dark card. A
   white tile makes the JPEG's own background disappear into it and gives the PNG the light ground
   it was drawn for, in both themes. The border keeps the tile from vanishing into a near-white page
   in light mode. The cost, stated: a logo drawn in white for dark backgrounds will not read — rare
   enough to be worth the trade, and the fallback is there if a company has no usable mark. */
.helion-company-logo {
  display: inline-flex; align-items: center; justify-content: center;
  flex: none; width: auto;
  background: #fff;
  border-radius: var(--helion-radius-sm); padding: var(--space-3) var(--space-4);
}
/* The size is set on the image, not the tile. Sized on the tile, the padding and border come out of
   the same box — a 44px tile left the logo 26px tall — so the number in the CSS was not the size
   anything actually rendered at. This way the height stated is the height drawn, and the tile grows
   to hold it. */
.helion-company-logo img { width: auto; max-width: 100%; object-fit: contain; display: block; }
.helion-company-logo-xs img { height: 18px; max-width: 64px; }
.helion-company-logo-sm img { height: 40px; max-width: 150px; }
.helion-company-logo-md img { height: 56px; max-width: 220px; }
/* The fallback takes the square the image does not, matching the height its logo would have had so
   a list of companies stays on one line whether or not each has a mark. Ink is fixed rather than
   themed because the tile is: --helion-fg would go pale against white in dark mode. */
.helion-company-logo-fallback {
  background: var(--brand, #fff);
  color: var(--brand-ink, #191b1f); font-weight: 600; font-family: 'Archivo', sans-serif; line-height: 1;
}
.helion-company-logo-xs.helion-company-logo-fallback { width: 18px; height: 18px; font-size: var(--text-2xs); }
.helion-company-logo-sm.helion-company-logo-fallback { width: 40px; height: 40px; font-size: var(--text-md); }
/* Tighter padding at this size — the tile is a marker beside a name, not a frame around a mark. */
.helion-company-logo-xs { padding: var(--space-1) var(--space-2); }

/* A company in a table cell: the mark for recognition, the name for everything else. Never the
   mark alone — not every company has a logo, and the fallback is an initial, so "Aplify" and a
   future "Acme" would both render "A" in the one column whose job is to say which row this is.
   A name also sorts, searches and reads at a glance for a company you have not seen before. */
.helion-company-cell { display: inline-flex; align-items: center; gap: var(--space-2); white-space: nowrap; }
.helion-company-cell > .helion-company-logo { flex: none; }
.helion-company-logo-md.helion-company-logo-fallback { width: 56px; height: 56px; font-size: var(--text-lg); }

/* The identifying block of a detail page: what the record is called, who it belongs to, and how it
   is labelled. Sits tight under the header for the same reason .helion-page-intro does — the three
   are one idea, and the page's real break comes after them. The chips are labels, not statuses:
   they say what the record is, so they carry no state colour. */
.helion-page-header:has(+ .helion-detail-identity) { margin-bottom: var(--space-3); }
/* One row, centred on itself: the mark and the labels answer "whose job, and what kind" together.
   Wraps rather than shrinks, so a long set of chips drops to its own line instead of squeezing the
   logo. */
.helion-detail-identity { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-3) var(--space-4); margin-bottom: var(--space-6); }
.helion-detail-identity-owner { font-size: var(--text-md); color: var(--helion-muted); display: flex; align-items: center; gap: var(--space-3); }

/* The logo beside its own file input, so what is set now and what would replace it are seen
   together rather than the preview sitting above an unrelated-looking control. */
.helion-logo-field { display: flex; align-items: flex-start; gap: var(--space-4); }
.helion-logo-field-input { flex: 1; min-width: 0; }

/* A card title marking AI-produced content. The gradient icon is the point of difference: a
   summary a model wrote should not look like a field somebody typed. Aligned on the text's
   optical centre, not its box, for the same reason the button icons are nudged. */
.helion-card-title-ai { display: flex; align-items: center; gap: var(--space-3); }
.helion-card-title-ai > svg { flex: none; margin-top: -1px; }

/* Rendered rich text — a job description from a feed, or anything else arriving as HTML we did
   not write. The reset strips list padding, and with list-style-position: outside the markers are
   then drawn beyond the list box: bullets hang into the card's own padding and read as though
   they have escaped the text. The indent puts them back inside the column. */
.helion-prose { max-width: var(--helion-measure); }
.helion-prose ul, .helion-prose ol { padding-left: var(--space-5); margin: 0 0 var(--space-4); }
.helion-prose li { margin-bottom: var(--space-2); }
.helion-prose li::marker { color: var(--helion-muted); }
.helion-prose p { margin: 0 0 var(--space-4); }
.helion-prose h2, .helion-prose h3 { font-size: var(--text-md); margin: var(--space-5) 0 var(--space-3); }
.helion-prose > :first-child { margin-top: 0; }
.helion-prose > :last-child { margin-bottom: 0; }

/* A disclosure for secondary content — the original text beside an AI rewrite. <details> rather
   than Alpine: it is a native disclosure, keyboard and screen-reader correct with no script. */
.helion-disclosure { margin-top: var(--space-5); border-top: 1px solid var(--helion-border); padding-top: var(--space-4); }
.helion-disclosure > summary {
  cursor: pointer; list-style: none; display: inline-flex; align-items: center; gap: var(--space-2);
  font-size: var(--text-sm); font-weight: 500; color: var(--helion-accent-strong);
}
.helion-disclosure > summary::-webkit-details-marker { display: none; }
/* The caret turns, so open and closed are told apart by more than the content below. */
.helion-disclosure > summary::after {
  content: ''; width: 12px; height: 8px; background: var(--helion-select-chevron) no-repeat center;
}
.helion-disclosure[open] > summary::after { transform: rotate(180deg); }
.helion-disclosure-body { margin-top: var(--space-4); }

/* A switcher between alternative views of one thing — an AI rewrite, the feed's own words, or the
   two side by side. Drawn as Helion's tabs, because that is already the vocabulary for "these are
   views of the same thing", but driven by radios rather than links: nothing navigates, and a radio
   group is a real keyboard and screen-reader control with no script behind it. The input is
   visually hidden rather than display:none, which would take it out of the tab order. */
/* The title and its switcher share a row, but there is not always width for both — so this header
   wraps where the general one does not. The extra space below it separates the controls from the
   text they act on: at the standard card spacing the copy started immediately under the tabs and
   the two read as one block. */
.helion-job-description > .helion-card-header { flex-wrap: wrap; margin-bottom: var(--space-7); }

.helion-switch { display: flex; align-items: center; gap: var(--space-5); flex-wrap: wrap; }
.helion-switch input {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.helion-switch label {
  padding: var(--space-2) 0; cursor: pointer;
  color: var(--helion-muted); font-size: var(--text-sm); font-weight: 500;
  background-image: var(--helion-accent-grad-x);
  background-repeat: no-repeat; background-position: left bottom; background-size: 0% 2px;
}
.helion-switch label:hover { color: var(--helion-fg); }
.helion-switch input:checked + label { color: var(--helion-fg); font-weight: 600; background-size: 100% 2px; }
/* The hidden input cannot show focus itself, so the label carries it. Without this the control is
   operable by keyboard but gives no sign of where you are. */
.helion-switch input:focus-visible + label {
  outline: 2px solid var(--helion-accent-strong); outline-offset: 4px; border-radius: var(--helion-radius-sm);
}
@media (prefers-reduced-motion: no-preference) {
  .helion-switch label { transition: color var(--dur) var(--ease), background-size var(--dur-slow) var(--ease); }
}

/* Panels. Only the selected one is shown, except in compare, where both are and the pair becomes a
   grid. Side by side rather than stacked because the question being asked is "did the rewrite
   change the meaning", and that is a comparison, not a read: stacked, you are holding the first
   version in your head by the time you reach the second.

   The pair splits the content column and nothing else on the page moves. An earlier version gave
   the whole page over to it — the aside dropped underneath and the job details and map went
   full-width, stacked, which looked like the page had come apart. The column is wide enough now to
   hold two texts without that.

   minmax(0, 1fr) rather than 1fr: a grid item's automatic minimum size is its content, and a feed
   description with one long unbroken string would otherwise push its column past its share. */
/* A panel is VISIBLE by default, and only hidden once a switcher exists to choose between them.
   It was the other way round — hidden by default, revealed by :has(#job-desc-…:checked) — which
   meant a job with no AI rewrite showed no description at all. The view only renders the radios
   when there is both a rewrite and an original, so with one description there is nothing to be
   checked, nothing matches, and the panel stays hidden with its text sitting in the HTML. That is
   what HC-One looked like: the feed had imported the description perfectly and the page was
   blank until "generate AI description" was ticked, which made it *visible* rather than fetching
   it. Hidden by default fails silently and invisibly; visible by default fails loudly. */
.helion-desc-panel { display: block; }
.helion-job-description:has(input[name="job-desc-view"]) .helion-desc-panel { display: none; }
.helion-desc-panel-label { font-size: var(--text-sm); font-weight: 500; color: var(--helion-muted); margin: 0 0 var(--space-3); display: none; }
.helion-job-description:has(#job-desc-ai:checked) .helion-desc-panel-ai,
.helion-job-description:has(#job-desc-original:checked) .helion-desc-panel-original,
.helion-job-description:has(#job-desc-compare:checked) .helion-desc-panel { display: block; }
.helion-job-description:has(#job-desc-compare:checked) .helion-desc-panels {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-6); align-items: start;
}
/* Each column needs naming once they are side by side; on its own the switcher already says which
   one you are looking at. */
.helion-job-description:has(#job-desc-compare:checked) .helion-desc-panel-label { display: block; }
.helion-job-description:has(#job-desc-compare:checked) .helion-desc-panel-original {
  border-left: 1px solid var(--helion-border); padding-left: var(--space-6);
}
/* Stacked well before phone width. Two columns are only worth having while each can hold a readable
   line, and the content column is already a fraction of the page: at a 1024px window it comes to
   448px, so the pair lands at 176px a side — about twenty characters, which is not a comparison,
   it is two ribbons. Above this the panels get roughly 420px each and the split earns its place. */
@media (max-width: 1360px) {
  .helion-job-description:has(#job-desc-compare:checked) .helion-desc-panels { grid-template-columns: 1fr; }
  .helion-job-description:has(#job-desc-compare:checked) .helion-desc-panel-original {
    border-left: 0; padding-left: 0; border-top: 1px solid var(--helion-border); padding-top: var(--space-5);
  }
}

/* Map. The tiles come from openstreetmap.org, so this is the one place a Helion page reaches a
   third party at render — worth knowing, given the fonts are self-hosted precisely to avoid that.
   No key and no library: the official embed carries its own marker. */
.helion-map { border-radius: var(--helion-radius-sm); overflow: hidden; border: 1px solid var(--helion-border); line-height: 0; }
.helion-map iframe { width: 100%; height: 240px; border: 0; display: block; }
.helion-map-caption { font-size: var(--text-2xs); color: var(--helion-muted); margin-top: var(--space-2); }

/* A card whose title carries its own action — the button acts on the card's contents, not
   on the page, so it belongs on the card's header row rather than in the page header. */
.helion-card-header { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); margin-bottom: var(--space-4); }
.helion-card-header .helion-card-title { margin-bottom: 0; }

.helion-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--helion-card-gap); margin-bottom: var(--helion-card-gap); }

/* Content beside its facts, for a detail page whose main content is prose.
   .helion-grid is the wrong tool there: its columns are equal, so a card holding text capped at
   var(--helion-measure) sits in a cell far wider than the text can fill, and the leftover shows as
   a hole inside the card rather than as margin. Measured on the job page before this existed, the
   description card was 1031px around 487px of prose — 53% of it empty.

   So the columns are deliberately unequal: the content column takes what is left, and the aside is
   fixed at a width that suits a dl and a map rather than a paragraph. minmax(0, 1fr) for the same
   overflow reason as .helion-compare above. */
/* A wider measure, for a detail page's main column where the text is the point and the aside is a
   sidebar. --helion-measure (58ch) comes out at 70 characters a line, which is already the top of
   the comfortable band; this is about 80, the most a line should carry before the eye starts
   losing its place returning to the left edge.

   It exists because the three things wanted here cannot all hold at once: a narrow sidebar, no
   slack in the content card, and a readable line. At a 320px aside, prose filling the card would
   run to 93 characters. This trades a little slack for a line that can still be read. */
/* Content beside a sidebar. The content column takes the room that is going; the aside is fixed,
   because a facts list and a map do not improve with width and a share of the page would grow them
   until they read as a second column rather than as support.

   The content column is NOT capped to a measure. Earlier versions were, and each time the cap held
   the text at a comfortable line the column looked starved beside everything around it — the fix
   kept being to raise the type so the measure grew with it, which ended at 20px body copy that read
   as clunky. On an admin page the reader is scanning a description whose shape they already know,
   not settling in to read an essay, so the line can run longer than prose typography would like.
   Width goes to the column, and the type stays at a normal size. */
.helion-detail-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 360px;
  gap: var(--helion-card-gap); align-items: start;
}
/* One step up from --text-base, which is a table-cell size and too small for continuous reading —
   and one step down from --text-lg, which filled the column but read as oversized. */
.helion-detail-layout .helion-prose { max-width: none; font-size: var(--text-md); }

/* Sticky so the salary and closing date stay readable while you are down in the description —
   the facts are what you are checking the text against. top clears the header's own padding. */
.helion-detail-aside { position: sticky; top: var(--space-5); }
/* Below this the aside is no longer beside anything, so it stops being sticky as well: a sticky
   block in a single column just pins itself over the content it is meant to accompany. */
@media (max-width: 900px) {
  .helion-detail-layout { grid-template-columns: 1fr; }
  .helion-detail-aside { position: static; }
}

/* Form actions sit outside the cards, so the primary action reads as applying to the whole form
   rather than to the last card above it. */
.helion-form-actions { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-1); }

/* Label kept for screen readers where the card title already names the field visually. */
.helion-visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --- Stat tiles --------------------------------------------------------------
   Counts are what people scan a company page for, so they get the largest type
   on the page and their own grid. IBM Plex Mono with tabular figures keeps
   numbers the same width, so a column of tiles stays optically aligned and a
   value doesn't shift as it changes. */
.helion-stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--helion-card-gap); margin-bottom: var(--helion-card-gap); }
.helion-stat {
  background: var(--helion-card-bg); border-radius: var(--helion-radius); padding: var(--space-6) var(--space-6);
  /* The corner wash is a token because the two themes need different gradients — see
     --helion-stat-wash. Set on background-image so the card colour above stays the background. */
  background-image: var(--helion-stat-wash);
  background-repeat: no-repeat;
  /* The grid stretches these to the hero's height, so distribute rather than stack: icon anchors
     the top, the number and its label anchor the bottom. Without this the content piles at the top
     and leaves a void that looks like something is missing — the fix is composition, not
     decoration. */
  display: flex; flex-direction: column; justify-content: space-between; gap: var(--space-6);
  /* Both are needed by the tone bar below, and a.helion-stat already sets them for its hover
     wash — declared here so the plain <div> tile gets them too. */
  position: relative; overflow: hidden;
}
/* Tone bar. Only drawn when the tile has been given an entity, so a tile without one keeps
   the old plain treatment rather than falling back to an arbitrary colour. */
.helion-stat[data-tone] { padding-left: calc(var(--space-6) + 6px); }
.helion-stat[data-tone]::after {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 6px;
  background: var(--tone); pointer-events: none;
  /* Above the linked tile's hover wash (z-index 0) and its content (z-index 1): the bar is
     the tile's identity, so it should survive the hover rather than be painted over by it. */
  z-index: 2;
}
/* Each tone carries its own ink, because they are not all light — see --helion-on-tone. */
.helion-stat[data-tone]                { --tone-ink: var(--helion-on-tone); }
.helion-stat[data-tone="jobs"]         { --tone: var(--helion-tone-jobs); --tone-ink: var(--helion-on-tone-light); }
.helion-stat[data-tone="applications"] { --tone: var(--helion-tone-applications); }
.helion-stat[data-tone="candidates"]   { --tone: var(--helion-tone-candidates); }
.helion-stat[data-tone="events"]       { --tone: var(--helion-tone-events); }
.helion-stat[data-tone="feeds"]        { --tone: var(--helion-tone-feeds); }
.helion-stat[data-tone="platform"]     { --tone: var(--helion-tone-platform); }

.helion-stat-icon {
  width: 38px; height: 38px; border-radius: 999px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--helion-tint-bg); color: var(--helion-muted);
}
.helion-stat[data-tone] .helion-stat-icon { background: var(--tone); color: var(--tone-ink); }
.helion-stat-value {
  font-family: 'IBM Plex Sans', sans-serif; font-variant-numeric: tabular-nums;
  /* 600 is the heaviest IBM Plex Sans weight loaded — 700 would be synthesised, which smears
     at 48-64px. If a count ever needs to be heavier than this, add the font file first. */
  font-size: var(--text-stat); font-weight: 600; line-height: 1; letter-spacing: -0.03em;
  color: var(--helion-heading);
}
.helion-stat-label { font-size: var(--text-sm); font-weight: 500; color: var(--helion-muted); margin-top: var(--space-2); }

/* Hero tile: the page's anchor, carrying the headline count plus its breakdown.
   Deep navy rather than the accent gradient — with tones on the plain tiles the colour of the
   page comes from them, and a gradient here would compete with six of them at once. The hero
   keeps NO tone bar for the same reason: it is the whole surface, so a 6px edge would be noise. */
.helion-stat-hero {
  grid-column: span 2; background: var(--helion-hero-bg); color: var(--helion-on-hero);
}
.helion-stat-hero.helion-stat[data-tone] { padding-left: var(--space-6); }
.helion-stat-hero.helion-stat[data-tone]::after { display: none; }
.helion-stat-hero .helion-stat-value,
.helion-stat-hero .helion-stat-label { color: var(--helion-on-hero); }
.helion-stat-hero .helion-stat-value { font-size: var(--text-stat-hero); }
.helion-stat-hero.helion-stat[data-tone] .helion-stat-icon,
.helion-stat-hero .helion-stat-icon { background: rgba(255,255,255,0.16); color: var(--helion-on-hero); }
.helion-stat-hero .helion-stat-label { color: var(--helion-on-hero-muted); }
/* The breakdown's divider and figures sit on navy now, not on the bright gradient, so they
   take light ink — the rgba(4,19,36,…) below is invisible against it. */
.helion-stat-hero .helion-stat-split > div:not(:last-child)::after { background: rgba(255,255,255,0.28); }
.helion-stat-hero .helion-stat-split-value { color: var(--helion-on-hero); }
.helion-stat-hero .helion-stat-split-label { color: var(--helion-on-hero); }
/* Headline and its breakdown on a single row, breakdown ranged right. A hero spans two columns,
   so stacking the two leaves the tile's width unused while driving its height up — and the grid
   sizes every tile in the row to the tallest. Wraps back to stacked when the tile is too narrow. */
.helion-stat-row { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-5); flex-wrap: wrap; }
.helion-stat-row .helion-stat-split { margin-top: 0; }

/* Breakdown row, divided rather than boxed — dividers cost less than more cards. */
.helion-stat-split { display: flex; gap: var(--space-5); margin-top: var(--space-1); }
.helion-stat-split > div { position: relative; padding-right: var(--space-5); }
.helion-stat-split > div:not(:last-child)::after {
  content: ''; position: absolute; right: 0; top: 0.1rem; bottom: 0.1rem;
  width: 1px; background: rgba(4,19,36,0.22);
}
.helion-stat-split-value {
  font-family: 'IBM Plex Sans', sans-serif; font-variant-numeric: tabular-nums;
  font-size: var(--text-xl); font-weight: 400; line-height: 1.2;
}
.helion-stat-split-label { font-size: var(--text-xs); opacity: 0.75; }
@media (max-width: 640px) { .helion-stat-hero { grid-column: span 1; } }

/* Setup progress. A feed's flow is add -> analyse -> check mappings -> import, but only the
   first and last are things you do, and nothing on the page said the middle steps existed: you
   created a feed, landed on its page, and the only button was Import. This shows the sequence
   and names the next action.

   Laid out as a row that wraps to a column on narrow widths rather than a fixed bar, so a step's
   detail line can say something useful ("12 fields mapped") instead of being clipped. No
   connector rules between markers — at four steps the reading order carries the sequence, and
   drawing lines that survive wrapping costs more than it returns. */
/* Its own bordered section rather than a strip floating between the tabs and the cards. The
   border is what makes it read as a considered piece of the page instead of stray markers, and
   it earns generous padding: this is the thing a first-time user reads before anything else. */
.helion-steps-block {
  border: 1px solid var(--helion-border); border-radius: var(--helion-radius);
  padding: var(--space-7) var(--space-6) var(--space-6);
  margin: var(--space-6) 0 var(--space-7);
}
/* --step-dot is the single source of truth for the dot's size: the track insets by half of it so
   the bar starts and ends at the outer dots' centres, and the fill's length is derived from the
   same figure. Change it in one place and the geometry follows. */
.helion-steps { position: relative; --step-dot: 36px; }

/* One continuous bar behind the dots rather than a segment each. Inset by half a dot so it runs
   between the first and last dot centres, and the fill is a fraction of that span — which is
   what lets a single element animate across the whole track. */
.helion-steps-track, .helion-steps-fill {
  position: absolute; top: calc(var(--step-dot) / 2 - 3px); height: 6px; border-radius: 999px;
  left: calc(var(--step-dot) / 2); z-index: 0;
}
.helion-steps-track { right: calc(var(--step-dot) / 2); background: var(--helion-track); }
.helion-steps-fill {
  width: calc((100% - var(--step-dot)) * var(--helion-steps-fraction, 0));
  background: var(--helion-accent-grad);
  transform-origin: left center;
}

.helion-steps-list { position: relative; z-index: 1; display: flex; list-style: none; margin: 0; padding: 0; }

/* The outer steps take half a column and align their dot to the edge, so the track spans the
   full width of the section instead of leaving a dead half-column at each end. The middle steps
   stay centred in full columns; dot spacing lands within a few pixels of even, which is far
   less noticeable than the inset was. */
.helion-step { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; text-align: center; }
.helion-step:first-child, .helion-step:last-child { flex: 0.5 1 0; }
.helion-step:first-child { align-items: flex-start; text-align: left; }
.helion-step:last-child  { align-items: flex-end;   text-align: right; }

.helion-step-marker {
  position: relative; z-index: 1;
  width: var(--step-dot); height: var(--step-dot); border-radius: 999px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--text-xs); font-weight: 600; font-variant-numeric: tabular-nums;
  /* Undone: the page ground with a track-coloured ring, so an empty dot reads as part of the
     same bar rather than as a separate object sitting on it. */
  background: var(--helion-bg); box-shadow: inset 0 0 0 2px var(--helion-track);
  color: var(--helion-muted-on-page);
}
/* Done and live are the same gradient in two combinations, per the brief: solid for finished,
   solid plus a halo for the one you are on. */
.helion-step.is-done .helion-step-marker {
  background: var(--helion-accent-grad); color: var(--helion-on-accent); box-shadow: none;
}
.helion-step.is-current .helion-step-marker {
  background: var(--helion-accent-grad); color: var(--helion-on-accent);
  box-shadow: 0 0 0 5px var(--helion-accent-halo);
}
.helion-step.is-failed .helion-step-marker {
  background: var(--helion-chip-attention); color: var(--helion-chip-attention-fg); box-shadow: none;
}

/* Labels sit under their dot, never across the bar. */
.helion-step-text { margin-top: var(--space-3); padding: 0 var(--space-2); min-width: 0; }
.helion-step-label { display: block; font-size: var(--text-sm); font-weight: 500; color: var(--helion-muted-on-page); }
.helion-step-detail { display: block; font-size: var(--text-2xs); color: var(--helion-muted-on-page); margin-top: var(--space-1); }
.helion-step.is-done .helion-step-label { color: var(--helion-fg); }
.helion-step.is-current .helion-step-label { color: var(--helion-heading); font-weight: 600; }
.helion-step.is-failed .helion-step-label { color: var(--helion-fg); }

.helion-steps-next {
  margin: var(--space-6) 0 0; padding-top: var(--space-5);
  border-top: 1px solid var(--helion-border);
  font-size: var(--text-sm); color: var(--helion-fg);
}
.helion-steps-next strong { color: var(--helion-heading); }

/* The fill grows from nothing rather than appearing, so progress reads as travelling along the
   track. Slower than --dur-deliberate because it covers the width of the section, not a tile
   corner — the same speed over a longer distance reads as a flick. Default state is filled, so
   reduced motion skips the animation rather than being left with an empty bar. */
@media (prefers-reduced-motion: no-preference) {
  .helion-steps-fill { animation: helion-steps-fill 900ms var(--ease) both; }
}
@keyframes helion-steps-fill { from { transform: scaleX(0); } }

@media (max-width: 640px) {
  /* Stacked, with the track dropped — a vertical bar needs different geometry and is not worth
     the complexity for four steps on a phone. */
  .helion-steps-track, .helion-steps-fill { display: none; }
  .helion-steps-list { flex-direction: column; gap: var(--space-5); }
  .helion-step, .helion-step:first-child, .helion-step:last-child {
    flex: 1 1 auto; flex-direction: row; align-items: center; gap: var(--space-4); text-align: left;
  }
  .helion-step-text { margin-top: 0; padding: 0; }
}

/* Chips listing the job vacancy fields a feed does not fill yet. Neutral badges throughout:
   these describe what is available, they are not statuses and must not read as one.

   The row gap is the larger one. When these wrap — and with twenty possible fields they will —
   a tight row gap runs the lines together, and pill-shaped items need more vertical clearance
   than plain text to read as separate rows rather than one dense block. */
.helion-chip-list { display: flex; flex-wrap: wrap; gap: var(--space-4) var(--space-5); margin-top: var(--space-5); }
.helion-chip-list > * { display: inline-flex; align-items: baseline; gap: var(--space-2); }
/* Intro text above a chip list needs its own clearance; without it the sentence sits on top of
   the first row of pills. */
.helion-chip-list-intro { margin: 0; }

/* Section label above a stat row. The dashboard shows platform-scoped figures and then
   company-scoped ones; unlabelled, the two rows read as one undifferentiated block of
   numbers and the change of scope is invisible. Set in the same muted micro-type as a
   table header, so it labels the row without competing with the page title. */
.helion-section-title {
  font-size: var(--text-2xs); font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--helion-muted-on-page); margin-bottom: var(--space-4);
}

/* A stat tile that is also a way in. Most tiles are only a figure, so this is opt-in —
   render the tile as a link solely where there is somewhere to go.

   On hover the accent gradient rises behind the tile, the icon lifts to a white disc and grows
   slightly, and the label crossfades to a call to action. The gradient is an ::before overlay
   rather than a background swap because background-image cannot be transitioned — fading a
   layer's opacity is the only way to avoid a hard jump.

   This does not compete with the hero: the hero is the page's one *persistent* accent moment,
   and only one tile can be hovered at a time. */
a.helion-stat { text-decoration: none; position: relative; overflow: hidden; }
a.helion-stat > * { position: relative; z-index: 1; }
/* Hover is ACHROMATIC, and that is the whole point now the tiles carry entity tones.
   It used to fade the accent gradient in. Once colour means "which entity", a hover that
   repaints the tile in a different hue is a second, competing use of colour — it replaced an
   orange tile with a blue-cyan one, and the tone bar (z-index 2) stayed orange on top of it,
   so both ideas were visible at once. The gradient also lost its resting place on the page
   when the hero went navy, leaving it appearing only under the cursor.

   So the tile takes the table's row tint instead — which is what this README said linked tiles
   should do all along, "rather than introducing a second hover colour". Colour now says one
   thing only: which entity this is.

   The row tint rather than --helion-control-bg, and that choice is measured. Lifting toward the
   raised "pressable" tone is the intuitive move and it does not work in light: the card sits at
   L* 96, so the raised tone reaches only ΔE 2.15 against it — under the ~3 floor, and under the
   2.7 this README already records as rejected for being invisible. The row tint reads ΔE 5.65
   in light and 3.80 in dark. Same trap as the stat wash, in a third place. */
a.helion-stat::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: var(--helion-tint-bg); opacity: 0;
}
a.helion-stat:hover::before,
a.helion-stat:focus-visible::before { opacity: 1; }

/* The ink darkens with the ground rather than staying put. On the tint, --helion-muted measures
   3.87 and even --helion-muted-on-page reaches only 4.42 — both under AA. Body ink clears it,
   and moving ground and ink together reads as one state change rather than two. Still entirely
   achromatic, so it does not reintroduce the second use of colour this treatment exists to
   remove. The value is already --helion-heading and needs nothing. */
a.helion-stat:hover .helion-stat-label,
a.helion-stat:focus-visible .helion-stat-label { color: var(--helion-fg); }

/* The icon keeps its tone chip rather than becoming a white disc: the disc existed to survive
   the gradient behind it, and there is no gradient now. Identity persists through the hover. */
a.helion-stat:hover .helion-stat-icon,
a.helion-stat:focus-visible .helion-stat-icon { transform: scale(1.08); }

/* The tile's own colour is what acknowledges the cursor — the bar thickens rather than a new
   hue arriving. Untoned tiles have no bar, so they get the surface lift and the CTA alone. */
a.helion-stat[data-tone]:hover::after,
a.helion-stat[data-tone]:focus-visible::after { width: 10px; }

/* The hero is a solid surface, so there is nothing to fade in — it lifts instead. 1.05 was
   enough on the old bright gradient; on navy a 5% lift is imperceptible, so it takes more. */
a.helion-stat-hero::before { display: none; }
a.helion-stat-hero:hover, a.helion-stat-hero:focus-visible { filter: brightness(1.45); }

/* Label crossfades to its CTA. Both sit in the same box with the CTA absolutely positioned, so
   nothing reflows; the real label stays in the DOM and the CTA is aria-hidden, which keeps the
   link's accessible name stable rather than changing it on hover. */
a.helion-stat .helion-stat-label { position: relative; display: inline-block; }
a.helion-stat .helion-stat-label-text { display: inline-block; }
a.helion-stat .helion-stat-cta {
  position: absolute; left: 0; top: 0; white-space: nowrap; opacity: 0;
  /* Heading ink, not --helion-on-accent: the hover ground is now one step up the neutral
     scale in each theme, so the CTA has to follow the theme rather than sit navy on both. */
  color: var(--helion-heading); font-weight: 600; transform: translateY(0.4em);
}
/* AFTER the rule above, deliberately. Both selectors are `a` plus two classes, so they have the
   same specificity and source order decides — placed before it, this silently lost and the CTA
   stayed brand navy on a navy hero at 1.43:1. The heading ink is right on a plain tile, whose
   hover ground is the light row tint; the hero is a dark surface and needs the opposite. */
a.helion-stat-hero .helion-stat-cta { color: var(--helion-on-hero); }
/* The two slide past each other rather than dissolving in place. A straight crossfade leaves
   both strings legible on top of one another through the middle of the transition, which reads
   as a rendering fault; moving them in opposite directions makes it a swap. */
a.helion-stat:hover .helion-stat-label-text,
a.helion-stat:focus-visible .helion-stat-label-text { opacity: 0; transform: translateY(-0.4em); }
a.helion-stat:hover .helion-stat-cta,
a.helion-stat:focus-visible .helion-stat-cta { opacity: 1; transform: translateY(0); }

@media (prefers-reduced-motion: no-preference) {
  a.helion-stat::before { transition: opacity var(--dur-deliberate) var(--ease); }
  a.helion-stat { transition: filter var(--dur-deliberate) var(--ease); }
  a.helion-stat[data-tone]::after { transition: width var(--dur-deliberate) var(--ease); }
  a.helion-stat .helion-stat-value,
  a.helion-stat .helion-stat-label { transition: color var(--dur-deliberate) var(--ease); }
  a.helion-stat .helion-stat-icon
    { transition: background var(--dur-deliberate) var(--ease), color var(--dur-deliberate) var(--ease), transform var(--dur-deliberate) var(--ease); }
  a.helion-stat .helion-stat-label-text,
  a.helion-stat .helion-stat-cta
    { transition: opacity var(--dur-deliberate) var(--ease), transform var(--dur-deliberate) var(--ease); }

  /* The CTA follows the gradient in rather than racing it, which is what makes the sequence read
     as one movement instead of several. The delay sits on the hover state only, so leaving the
     tile reverses immediately — a lag on exit feels like the page is behind the cursor. */
  a.helion-stat:hover .helion-stat-cta,
  a.helion-stat:focus-visible .helion-stat-cta { transition-delay: var(--dur); }
  a.helion-stat:hover .helion-stat-label-text,
  a.helion-stat:focus-visible .helion-stat-label-text { transition-duration: var(--dur-slow); }
}

/* Detail rows — label above value, so a long address wraps without pushing its
   label out of line the way a two-column dl does. */
.helion-detail { display: flex; flex-direction: column; gap: var(--space-4); }
.helion-detail-row { display: flex; align-items: flex-start; gap: var(--space-4); }
.helion-detail-icon {
  width: 30px; height: 30px; border-radius: 999px; flex: none; margin-top: var(--space-1);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--helion-tint-bg); color: var(--helion-muted);
}
.helion-detail-label { font-size: var(--text-xs); font-weight: 500; color: var(--helion-muted); }
.helion-detail-value { font-size: var(--text-base); overflow-wrap: anywhere; }   /* see .helion-dl dd */

/* Definition lists do the same job as .helion-detail on the company page — a label and its value —
   so they take the same typographic treatment. Laid out in columns on wide cards, because a long
   list of short values reads as a column of orphans otherwise. */
/* Multi-column, not grid. A grid treats dt and dd as independent items, so a label and its value
   stay together only when the column count happens to be even — at three columns every pair split,
   and the card read as nonsense. Which count you get depends on the card's width, so this looked
   correct on a narrow window and broke on a wide one.

   Multi-column keeps each pair in normal flow within its column, so they cannot separate however
   many columns fit. The break rules stop a pair straddling a column boundary. */
.helion-dl { columns: 240px 3; column-gap: var(--space-5); }
.helion-dl dt { font-size: var(--text-2xs); font-weight: 500; color: var(--helion-muted); margin: 0; break-after: avoid; page-break-after: avoid; }
/* overflow-wrap: anywhere because these hold values we do not control the length of. A feed URL
   with a query string has no break opportunity, and inside a 240px column it does not wrap — it
   runs straight out past the card's edge and over whatever sits beside it. "anywhere" rather than
   "break-word" so the value also counts toward min-content width, which is what multicol uses to
   size the column. Only shows up with real data; every seeded URL was short enough to fit. */
.helion-dl dd { font-size: var(--text-base); color: var(--helion-fg); margin: 0 0 var(--space-4); break-inside: avoid; page-break-inside: avoid; overflow-wrap: anywhere; }

/* A list that should stay one column whatever width it is given. In an aside the column count
   above happens to come out at one already, but that is the aside's current width deciding it, not
   the list: widen the aside past ~500px and a four-row facts list silently becomes two columns of
   two, which reads as two unrelated pairs. Stated rather than inferred. */
.helion-dl-single { columns: 1; }

/* A row of chips that wraps. Chips are inline-level, so without this they inherit the surrounding
   line-height and the wrapped rows sit too close to be read as separate rows. */
.helion-chip-row { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }

/* A chip carrying an icon — a place, most often. The icon is a hint at what the value is, so it
   takes the chip's own colour rather than standing out from it.
   Qualified with .helion-badge because that rule is declared later in this file: on a single class
   each it wins on source order, and the chip renders as a block with the icon stacked above the
   text, half again as tall as its neighbours. */
.helion-badge.helion-badge-icon { display: inline-flex; align-items: center; gap: var(--space-1); }
.helion-badge-icon > svg { width: 12px; height: 12px; flex: none; }

/* Trailing chips under a list, separated from the last value rather than crowding it. */
.helion-detail-footnote-row { margin-top: var(--space-4); }

.helion-muted { color: var(--helion-muted); }

/* A value a model produced, sitting inline among values people typed. The card title's ai mark
   (.helion-card-title-ai) says "this card holds generated content"; this says it about one value.
   Needed most on a salary: it is the one generated figure a candidate acts on, and unmarked it is
   indistinguishable from what the recruiter actually wrote.

   The icon is smaller than the title's 18px and is pushed to the start, so a right-ranged figure on
   a job card still ends flush with the column. align-items: baseline rather than center so the mark
   sits on the text's line rather than the box's middle. */
.helion-ai-value { display: inline-flex; align-items: baseline; gap: var(--space-2); }
.helion-ai-value > svg { width: 13px; height: 13px; flex: none; align-self: center; }

/* A link that leaves the app. The icon is the marker; the visually-hidden text is what actually
   announces it, since an icon in an <img>-less <svg> says nothing to a screen reader and a new tab
   opening unannounced is disorienting.

   Deliberately NOT inline-flex. These carry a feed URL with a long query string, which has no break
   opportunity and is only kept inside its card by overflow-wrap: anywhere on the dd — a flex
   container makes the URL an unbreakable flex item again and it runs straight out past the card's
   edge, which is a bug this codebase has already had once. Inline with vertical-align keeps the
   text wrapping exactly as it did. */
.helion-link-external > svg { display: inline-block; vertical-align: -2px; margin-left: var(--space-1); opacity: 0.75; }

/* A secondary line under a primary one — who did it, when, which job it was against. These were
   written inline as `class="helion-muted" style="font-size: 0.8rem"` in fourteen places across six
   views. 0.8rem is not a step on the scale: it sits between --text-xs and --text-sm, so every one
   of them was a hand-picked size that matched nothing else on the page. Colour is part of the class
   because it was part of every one of those usages. */
.helion-meta { font-size: var(--text-sm); color: var(--helion-muted); }
/* The finer one, for a bare timestamp sitting under content that already says what it refers to. */
.helion-meta-xs { font-size: var(--text-xs); color: var(--helion-muted); }

/* An entry in a divided list — a timeline, a run of notes. The rule separates entries rather than
   boxing each one: dividers cost less than more cards, as with .helion-stat-split. */
.helion-divided-entry {
  margin-bottom: var(--space-3); padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--helion-border);
}
/* The same list without the rule, where each entry is one line and a divider per line would be
   more rule than content. */
.helion-history-entry { margin-bottom: var(--space-2); }

/* A disclosure inside a card's body rather than closing it off — no rule above it, unlike
   .helion-disclosure, which separates a whole secondary section from the card's main content. */
.helion-inline-details { margin-top: var(--space-3); }
.helion-inline-details > summary { cursor: pointer; }
/* Long text given a fixed height and its own scroll, so a 20,000-character feed description cannot
   push the rest of the page out of reach. */
.helion-scroll-box {
  max-height: 200px; overflow-y: auto;
  margin-top: var(--space-2); font-size: var(--text-sm);
}

.helion-page-header { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); margin-bottom: var(--space-6); }

/* Header actions must be a flex row, because button_to renders a <form> — a block element, which
   drops every non-link action onto a line of its own. The table styles already correct this for
   row actions; the header never did, so any page with more than one button stacked raggedly. */
.helion-page-actions { display: flex; align-items: center; gap: var(--space-2); flex-shrink: 0; }
.helion-page-actions form.button_to { display: inline-block; margin: 0; }

/* --- Tabs --- */

/* Sub-pages of a record — an event's form fields and registrations, a feed's mappings and reports
   — are navigation, not actions. Rendered as header buttons they were indistinguishable from
   Delete, which is what made those headers unreadable.

   The active tab carries the brand gradient underline, the same treatment as a focused field, so
   both read as one idea: this is the live one. No baseline rule under the strip — Meridian keeps
   rules for tables, where a scannable list needs delineation padding cannot give. */
.helion-tabs { display: flex; align-items: center; gap: var(--space-5); margin-bottom: var(--space-6); flex-wrap: wrap; }
.helion-tab {
  padding: var(--space-2) 0;
  color: var(--helion-muted); text-decoration: none;
  font-size: var(--text-sm); font-weight: 500;
  background-image: var(--helion-accent-grad-x);
  background-repeat: no-repeat; background-position: left bottom;
  background-size: 0% 2px;
  transition: color var(--dur) var(--ease), background-size var(--dur-slow) var(--ease);
}
.helion-tab:hover { color: var(--helion-fg); }
.helion-tab.is-active { color: var(--helion-fg); font-weight: 600; background-size: 100% 2px; }

/* --- Overflow menu --- */

/* For actions that should not occupy the header: editing, destructive work, and the long tail of
   one-off operations a feed accumulates. */
.helion-menu { position: relative; }
.helion-menu-panel {
  position: absolute; top: calc(100% + var(--space-2)); right: 0; z-index: 300;
  min-width: 210px; padding: var(--space-2);
  background: var(--helion-card-bg);
  /* The sidebar's dropdown needs no edge because card-on-navy is a large contrast. This one floats
     on the page ground, where card-on-page measures ΔE 3.0 — barely a boundary. Hence the border. */
  border: 1px solid var(--helion-border);
  border-radius: var(--helion-radius-sm);
  display: flex; flex-direction: column; gap: var(--space-1);
}
.helion-menu-panel form.button_to { margin: 0; }
.helion-menu-item,
.helion-menu-panel form.button_to > button {
  display: block; width: 100%; text-align: left;
  padding: var(--space-2) var(--space-3);
  border: none; border-radius: var(--helion-radius-sm);
  background: none; color: var(--helion-fg);
  font-family: inherit; font-size: var(--text-sm); font-weight: 500;
  text-decoration: none; cursor: pointer;
  transition: background-color var(--dur) var(--ease);
}
.helion-menu-item:hover,
.helion-menu-panel form.button_to > button:hover { background: var(--helion-tint-bg); }
.helion-menu-item.is-danger,
.helion-menu-panel form.button_to > button.is-danger { color: var(--helion-error); }
/* A divider is the one place this component earns a rule: it separates destructive actions from
   ordinary ones, a boundary worth drawing rather than implying with space. */
.helion-menu-sep { height: 1px; margin: var(--space-1) var(--space-2); background: var(--helion-border); }

/* An intro belongs to its title, so they sit close; the big break comes after the pair. */
.helion-page-header:has(+ .helion-page-intro) { margin-bottom: var(--space-3); }
.helion-page-intro {
  max-width: var(--helion-measure);
  font-size: var(--text-md); line-height: 1.6; color: var(--helion-muted);
  margin-bottom: var(--space-7);
}
.helion-page-header h2 { font-size: var(--text-3xl); }

/* cursor: pointer is not redundant here. This class lands on both <a> (View, Edit) and <button>
   (every button_to row action, and submits like the dashboard's Search) — anchors get the pointer
   from the browser, buttons do not, so without it the button-rendered half looked unclickable.
   .helion-btn, .helion-btn-toggle and .helion-company-toggle already set it. */
.helion-btn-small { display: inline-flex; align-items: center; vertical-align: middle; gap: var(--space-1); font-size: var(--text-sm); padding: var(--space-2) var(--space-4); background: var(--helion-control-bg); border: 1px solid var(--helion-control-edge); border-radius: 999px; text-decoration: none; color: var(--helion-fg); cursor: pointer; }
.helion-btn-small:hover { background: var(--helion-control-bg-hover); }
.helion-btn-small:active { transform: translateY(1px); }

/* Checkbox and radio share everything but the corner radius and the checked indicator.
   The native controls are replaced outright — OS chrome was the most off-brand thing on the form. */
.helion-checkbox, .helion-radio { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); cursor: pointer; }
/* .helion-checkbox-input is the same control without a wrapping label — for a table cell, where the
   column heading is already the label and there is no text to sit beside. */
.helion-checkbox input, .helion-radio input, .helion-checkbox-input {
  appearance: none; -webkit-appearance: none; flex: none; margin: 0;
  width: 18px; height: 18px; background: var(--helion-input-bg); cursor: pointer;
  display: grid; place-content: center;
}
.helion-checkbox input, .helion-checkbox-input { border-radius: 6px; }
.helion-radio input { border-radius: 999px; }
.helion-checkbox input:hover, .helion-radio input:hover, .helion-checkbox-input:hover { background: var(--helion-input-bg-hover); }
.helion-checkbox input::before, .helion-radio input::before, .helion-checkbox-input::before { content: ''; background: #fff; transform: scale(0); }
/* Tick for checkbox, dot for radio. */
.helion-checkbox input::before, .helion-checkbox-input::before {
  width: 11px; height: 11px;
  clip-path: polygon(14% 44%, 0 60%, 40% 100%, 100% 22%, 84% 6%, 38% 68%);
}
.helion-radio input::before { width: 7px; height: 7px; border-radius: 999px; }
.helion-checkbox input:checked, .helion-radio input:checked, .helion-checkbox-input:checked { background: var(--helion-accent-grad); }
.helion-checkbox input:checked::before, .helion-radio input:checked::before, .helion-checkbox-input:checked::before { transform: scale(1); }
.helion-checkbox input:disabled, .helion-radio input:disabled, .helion-checkbox-input:disabled { opacity: 0.5; cursor: not-allowed; }

/* --- Tables --- */

/* Tables are the one place Meridian keeps a rule: rows in a scannable list need delineation that
   padding alone can't give. It uses the warm --helion-border token at hairline weight so it reads
   as texture rather than as a box. The header carries no rule at all — it's set as muted micro-type
   instead, so the eye starts on the data. */
.helion-table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.helion-table th {
  text-align: left; font-weight: 600; font-size: var(--text-2xs); letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--helion-muted);
  padding: 0 var(--space-3) var(--space-2); white-space: nowrap; border: none;
}
.helion-table td { height: var(--table-row-h); padding: var(--space-2) var(--space-3); border: none; border-top: 1px solid var(--helion-border); vertical-align: middle; }
.helion-table tbody tr:first-child td { border-top: none; }
.helion-table tbody tr:hover td { background: var(--helion-tint-bg); }
.helion-table td:first-child { border-radius: var(--helion-radius-sm) 0 0 var(--helion-radius-sm); }
.helion-table td:last-child { border-radius: 0 var(--helion-radius-sm) var(--helion-radius-sm) 0; }
.helion-table .helion-row-muted { opacity: 0.45; }
/* The last column is the row's actions, and it is pinned to the table's right edge: width 1%
   makes the browser give it its content width and hand the remainder to the data columns. That
   is what lets two tables with different column counts — Feed health has five, Companies has
   four — line their buttons up with each other instead of wherever their content happened to
   end. Content columns spread into the space rather than bunching left.

   NOT every table ends in actions. Five end in data (candidates/show, the ATS sync log,
   exported_feeds form and show, and the second approvals table), and they opt out with
   .helion-table-no-actions — otherwise a date or an error message gets right-aligned and
   squeezed to its content width. */
.helion-table:not(.helion-table-no-actions) th:last-child,
.helion-table:not(.helion-table-no-actions) td:last-child { text-align: right; width: 1%; }
.helion-table:not(.helion-table-no-actions) td:last-child { white-space: nowrap; }
/* button_to renders a <form>, which is block-level and would stack the action controls one per
   line. Keep them inline, and space them so Edit/Reset don't read as a single word. */
.helion-table form.button_to { display: inline-block; margin: 0; vertical-align: middle; }
.helion-table td > .helion-link,
.helion-table td > .helion-btn-small,
.helion-table td > form.button_to { margin-right: var(--space-2); }
/* Row-scale buttons: the standard .helion-btn-small is sized for page headers and reads chunky
   inside a table row. Same class, compact metrics — matching the chips beside it. */
.helion-table .helion-btn-small { font-size: var(--text-xs); padding: var(--space-1) var(--space-3); }

/* Badges are fully-rounded solid chips from the Signal scale. Bare .helion-badge is the quiet
   neutral — used for chips that describe configuration rather than signal state. */
.helion-badge {
  display: inline-block; font-size: var(--text-2xs); font-weight: 600; letter-spacing: 0.01em;
  padding: 0.28em 0.75em; border-radius: 999px; border: none; white-space: nowrap;
  background: var(--helion-chip-neutral); color: var(--helion-chip-neutral-fg);
  margin-left: var(--space-1); vertical-align: middle;
}
/* Solid chips carry state that needs noticing; tinted chips merely classify. The loudest thing in
   a row should be the most important — "Standard" only means "this is a default field", so it must
   not outshout Required or Visible. */
.helion-badge-info      { background: var(--helion-info-bg);        color: var(--helion-info); }
.helion-badge-success   { background: var(--helion-chip-success);   color: var(--helion-chip-success-fg); }
.helion-badge-attention { background: var(--helion-chip-attention); color: var(--helion-chip-attention-fg); }
.helion-badge-warn      { background: var(--helion-chip-warning);   color: var(--helion-chip-warning-fg); }
.helion-badge-teal      { background: var(--helion-chip-teal);      color: var(--helion-chip-teal-fg); }
.helion-badge-slate     { background: var(--helion-chip-slate);     color: var(--helion-chip-slate-fg); }
.helion-badge-rose      { background: var(--helion-chip-rose);      color: var(--helion-chip-rose-fg); }
/* Solid violet for a status, where .helion-badge-info is the quiet tinted version used to classify.
   A pipeline stage is a signal, so it takes the solid chip. */
.helion-badge-violet    { background: var(--helion-chip-info);      color: var(--helion-chip-info-fg); }

.helion-indent { color: var(--helion-muted); margin-right: var(--space-1); }

/* Reorder arrows — circular tint buttons, same family as .helion-icon-btn in the header. */
.helion-btn-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0; border: 1px solid var(--helion-control-edge); border-radius: 999px;
  background: var(--helion-control-bg); color: var(--helion-fg);
  cursor: pointer; font-size: var(--text-2xs); font-family: inherit;
}
.helion-btn-icon:hover { background: var(--helion-control-bg-hover); }
.helion-btn-icon:active { transform: translateY(1px); }

/* Toggles read as chips too, so a row can be scanned down a column. Off is the quiet neutral;
   `is-on` fills solid. Required-on uses attention rather than success — a required field is a
   constraint to notice, not a good outcome, and red must stay reserved for genuine problems. */
.helion-btn-toggle {
  border: 1px solid var(--helion-control-edge); border-radius: 999px; cursor: pointer; font-family: inherit;
  font-size: var(--text-xs); font-weight: 600; padding: var(--space-1) var(--space-3);
  background: var(--helion-control-bg); color: var(--helion-fg);
}
.helion-btn-toggle.is-on { background: var(--helion-chip-success); color: var(--helion-chip-success-fg); border-color: transparent; }
.helion-btn-toggle.is-on.is-attention { background: var(--helion-chip-attention); color: var(--helion-chip-attention-fg); }
.helion-btn-toggle:not(.is-on):hover { background: var(--helion-control-bg-hover); }
.helion-btn-toggle.is-on:hover { filter: brightness(0.94); }
.helion-btn-toggle:active { transform: translateY(1px); }

/* --helion-primary was an old-palette token Meridian removed; this rendered colourless. */
.helion-link-btn { background: none; border: none; cursor: pointer; color: var(--helion-accent-strong); font-size: var(--text-sm); font-family: inherit; padding: 0; }
.helion-link-btn:hover { text-decoration: underline; }
.helion-link-danger { color: var(--helion-chip-attention); }

/* --- Field rows --- */

/* The row's gap is a between-group gap too — two fields side by side are two groups — so it
   matches the vertical one rather than staying at the old 16px. */
.helion-field-row { display: flex; flex-wrap: wrap; gap: var(--space-5); margin-bottom: var(--space-5); }
.helion-field-row .helion-field { flex: 1; min-width: 150px; margin-bottom: 0; }

/* --- Color input --- */

/* Chrome draws its own 1px border on the swatch AND insets it via the wrapper's padding, which
   is what leaves a dark ring. Both have to be reset, and appearance:none stops the UA restyling. */
.helion-input-color {
  appearance: none; -webkit-appearance: none;
  width: 64px; height: 40px; padding: 4px; border: none;
  border-radius: var(--helion-input-radius); background: var(--helion-input-bg); cursor: pointer;
}
.helion-input-color::-webkit-color-swatch-wrapper { padding: 0; border: none; }
.helion-input-color::-webkit-color-swatch { border: none; border-radius: 8px; }
.helion-input-color::-moz-color-swatch { border: none; border-radius: 8px; }

/* File input: the native control ships an OS-styled button that ignores the field's fill.
   ::file-selector-button is the only hook for it — style it as a quiet pill. */
.helion-input[type="file"] {
  display: flex; align-items: center; padding: var(--space-2) var(--space-2); cursor: pointer;
  font-size: var(--text-sm); color: var(--helion-muted);
}
.helion-input[type="file"]::file-selector-button {
  border: none; border-radius: 999px; cursor: pointer; font-family: inherit;
  font-size: var(--text-xs); font-weight: 600; padding: var(--space-2) var(--space-4); margin-right: var(--space-3);
  background: var(--helion-control-bg); color: var(--helion-fg);
}
.helion-input[type="file"]::file-selector-button:hover { background: var(--helion-control-bg-hover); }

/* Placeholder tokens in help text read as data, so give them a mono chip rather than leaving
   them as an undifferentiated run of prose. */
.helion-help-text code {
  font-family: 'IBM Plex Mono', monospace; font-size: var(--text-xs);
  background: var(--helion-chip-neutral); color: var(--helion-chip-neutral-fg);
  padding: 0.15em 0.45em; border-radius: 6px; white-space: nowrap;
}

/* A bare checkbox followed by a field ran straight into the field's label, making the label look
   like it belonged to the checkbox. */
.helion-checkbox + .helion-field { margin-top: var(--space-4); }

/* --- Logo preview --- */

.helion-logo-preview { margin-bottom: var(--space-2); }

/* --- Help text --- */

/* --text-xs, not --text-sm: see .helion-label. space-2 rather than space-1 because 4px under a
   44px control read as a collision — the note was clinging to the field twice as hard as the
   label sat above it. */
.helion-help-text { font-size: var(--text-xs); color: var(--helion-muted); margin-top: var(--space-2); }
/* Help that INTRODUCES a grid of choice tiles rather than annotating a control it follows. A note
   placed under a wrapping grid is orphaned — it sits below whichever tile happened to land last
   and no longer reads as belonging to the label — so for multi-choice grids the guidance goes
   first and carries the gap on its other side. A single control keeps its note underneath. */
.helion-help-text-lead { margin-bottom: var(--space-3); }
/* Running copy that introduces a CARD, as against a note annotating a field. It wore the field
   note's class and then re-declared its bottom margin inline at all fourteen call sites, which is
   the tell that it was a second role borrowing the first one's name. It keeps --text-sm: a
   300-character paragraph does not want a field note's size. */
.helion-card-intro { font-size: var(--text-sm); color: var(--helion-muted); margin-bottom: var(--space-4); }

/* A detail value with a chip beside it, and a note underneath. A chip is a different shape from
   the text it follows, so the single word space they would otherwise share reads as a collision;
   and a note sitting under a chip needs more clearance than one under a line of text, which is
   what --space-1 is tuned for. */
.helion-dd-row { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.helion-dd-row + .helion-help-text { margin-top: var(--space-3); }

/* Help text belonging to a checkbox hangs under its label, not under the control. The indent is
   the control's own width plus the flex gap — off-scale because it's tied to the 18px box, not to
   a rhythm. Without it the text restarts at the margin and reads as a new item. */
.helion-checkbox + .helion-help-text { margin-left: calc(18px + var(--space-2)); }

/* --- Selectable checkbox tiles --- */

/* A cluster of independent options reads better as pressable objects than as a column of bare
   controls. The resting fill is --helion-control-bg because the tone scale says light means
   pressable; the tile must never take the field fill or it would read as somewhere to type.

   The checked state is carried by the border, which measures 2.70:1 against the tile fill. The
   accent tint is only 1.10:1 by contrast ratio — but contrast ratio sees lightness, not hue, and
   the tint is ΔE 8.5 where the neutral wash rejected on the stat tiles was ΔE 2.7. So the tint is
   a genuine second signal here, not a repeat of that mistake. Border first, tint supporting. */
.helion-check-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--space-3);
}
.helion-check-tile {
  display: block; padding: var(--space-4);
  border-radius: var(--helion-input-radius);
  background: var(--helion-control-bg);
  border: 1px solid var(--helion-control-edge);
  cursor: pointer;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.helion-check-tile:hover { background: var(--helion-control-bg-hover); }
.helion-check-tile:has(input:checked) {
  border-color: var(--helion-accent); background: var(--helion-accent-bg);
}
/* Keyboard focus has to be visible independently of checked, so it uses an outline rather than the
   border — otherwise focusing an already-checked tile would show no change at all. */
.helion-check-tile:focus-within { outline: 2px solid var(--helion-accent); outline-offset: 2px; }
.helion-check-tile .helion-help-text { margin-left: calc(18px + var(--space-2)); }

/* An input sized to its content rather than the column — a position ordinal is two digits, and a
   full-width field would imply there is more to type. */
.helion-input-narrow { width: 4.5rem; }

/* Supporting text inside a table cell — a sample value beside the field it belongs to. Steps down
   from the row's own size rather than picking a bespoke one. */
.helion-table-example { font-size: var(--text-xs); }

/* --- Monospace input --- */

.helion-input-mono { font-family: 'IBM Plex Mono', monospace; font-size: var(--text-sm); }

/* --- Template actions --- */

/* Flex with a gap replaces the literal "|" separator between the two actions. The revealed
   default template is a flex child too, so it needs a full-width basis to drop onto its own line. */
.helion-template-actions { margin-top: var(--space-2); font-size: var(--text-sm); display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.helion-template-default { flex-basis: 100%; margin-top: var(--space-2); }
.helion-pre {
  background: var(--helion-input-bg); border: none; border-radius: var(--helion-input-radius);
  padding: var(--space-4) var(--space-4); font-family: 'IBM Plex Mono', monospace; font-size: var(--text-xs);
  white-space: pre-wrap; overflow-x: auto;
}

/* --- Narrow screens ----------------------------------------------------------
   The desktop layout is built on a fixed sidebar that everything else is offset
   from, via --helion-sidebar-current. On a phone that rail eats a third of the
   screen, so below this breakpoint the sidebar leaves the flow entirely and
   becomes an overlay drawer: the offset token goes to 0 and the sidebar slides
   in over the content instead of pushing it. Everything downstream — header,
   main, the bleeding nav pill — follows from that one token, so nothing else
   needs repositioning. */
@media (max-width: 768px) {
  html,
  html.helion-sidebar-expanded { --helion-sidebar-current: 0px; }

  .helion-sidebar {
    width: min(var(--helion-sidebar-width), 82vw);
    /* Slide past the bleed as well as the width: the active pill deliberately overhangs the
       sidebar's right edge, so -100% alone leaves that overhang visible at the screen edge. */
    transform: translateX(calc(-100% - var(--helion-nav-bleed)));
    z-index: 200;
  }
  html.helion-sidebar-expanded .helion-sidebar { transform: translateX(0); }

  /* Labels and the wordmark are driven by .helion-sidebar-expanded, which is
     exactly the state the drawer is open in, so they reveal without extra rules. */

  .helion-scrim {
    position: fixed; inset: 0; z-index: 150;
    background: rgba(4, 19, 36, 0.45);
    opacity: 0; pointer-events: none; transition: opacity var(--dur) var(--ease);
  }
  html.helion-sidebar-expanded .helion-scrim { opacity: 1; pointer-events: auto; }

  .helion-header { padding: 0 var(--space-4); gap: var(--space-2); }
  .helion-header-center { min-width: 0; overflow: hidden; }
  .helion-header-right { gap: var(--space-1); }

  .helion-main { padding: var(--space-4) var(--space-4) 2.5rem; }

  /* Title and action stack rather than colliding when the title is long. */
  .helion-page-header { flex-wrap: wrap; gap: var(--space-3); }
  .helion-page-header h2 { font-size: var(--text-2xl); }

  .helion-card { padding: var(--space-5) var(--space-5); }
  .helion-stat { padding: var(--space-5) var(--space-5); gap: var(--space-5); }
  .helion-stat-hero .helion-stat-value { font-size: var(--text-stat); }
  .helion-stat:not(.helion-stat-hero) .helion-stat-value { font-size: var(--text-2xl); }
  .helion-card-title { font-size: var(--text-lg); }

  /* A six-column table cannot shrink to 375px without becoming unreadable, so it
     scrolls sideways inside its card rather than crushing or overflowing the page. */
  .helion-card:has(> .helion-table) { overflow-x: auto; }
  .helion-table { min-width: 640px; }

  /* Side-by-side form fields stack. */
  .helion-field-row { flex-direction: column; gap: 0; }
  .helion-field-row .helion-field { min-width: 0; margin-bottom: var(--space-4); }
}

@media (min-width: 769px) { .helion-scrim { display: none; } }

@media (prefers-reduced-motion: no-preference) {
  .helion-sidebar { transition: transform var(--dur) var(--ease), width var(--dur) var(--ease); }
}

@media (max-width: 768px) { .helion-header-brand { display: flex; } }

/* Empty states are an invitation to act, not a blank panel. */
.helion-empty { text-align: center; padding: var(--space-7) var(--space-5); }
.helion-empty-title { font-size: var(--text-md); font-weight: 600; color: var(--helion-heading); margin-bottom: var(--space-2); }
.helion-empty-body { font-size: var(--text-base); color: var(--helion-muted); max-width: 44ch; margin: 0 auto var(--space-5); }

/* Motion is for explaining, not decorating. Two cases earn it:

   1. The dropdown scales from its trigger, so it reads as belonging to the button that opened it
      rather than appearing from nowhere.
   2. A flash is the one thing on a page the user did NOT ask to see — it is the result of an
      action, so a brief arrival marks it as new. This is why it animates on load and page content
      deliberately does not: content you clicked for was already justified by the click, and
      animating it on every Turbo navigation would just make the app feel slow.

   Everything else — page content, cards, table rows — appears instantly, on purpose. */
@media (prefers-reduced-motion: no-preference) {
  .helion-company-dropdown {
    transform-origin: top left;
    animation: helion-pop var(--dur) var(--ease);
  }
  .helion-flash { padding: var(--space-2) var(--space-4); border-radius: var(--helion-radius-sm); margin-bottom: var(--space-4); font-size: var(--text-sm); }
}
@keyframes helion-pop {
  from { opacity: 0; transform: scale(0.96) translateY(-4px); }
  to   { opacity: 1; transform: none; }
}
@keyframes helion-arrive {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

/* Row actions recede until the row is hovered, so a long table reads as data rather than as a wall
   of buttons — the eye finds the row it wants first, then the controls.
   Guarded by (hover: hover): on touch there is no hover state, so they must stay fully visible.
   :focus-within keeps them reachable by keyboard, where there is no pointer to reveal them. */
@media (hover: hover) {
  /* LAST child only. This also faded td:first-child, which is the row's own name or reference —
     "It is the row, not an action on it", as the README puts it — so every table rendered its
     identifier at half opacity until hovered. Nothing in the comment above justified it and
     nothing in the README asked for it. */
  .helion-table:not(.helion-table-no-actions) tbody td:last-child { opacity: 0.5; }
  .helion-table:not(.helion-table-no-actions) tbody tr:hover td:last-child,
  .helion-table:not(.helion-table-no-actions) tbody tr:focus-within td:last-child { opacity: 1; }
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .helion-table:not(.helion-table-no-actions) tbody td:last-child { transition: opacity var(--dur) var(--ease); }
}

/* --- Chart primitives ---------------------------------------------------------
   Plain CSS/SVG, no charting library. Whatever library eventually arrives should be
   fed these tokens rather than bringing its own palette.

   Marks are thin, data-ends are rounded and anchored to the baseline, and a 2px
   surface-coloured gap separates adjacent fills so segments read as distinct. */

/* Meter — a single proportion. Needs a denominator; do not use it for a bare count. */
.helion-meter { height: 10px; border-radius: 999px; background: var(--chart-track); overflow: hidden; }
.helion-meter-fill { height: 100%; border-radius: 999px; background: var(--chart-1); }
.helion-meter-fill.is-accent { background: var(--helion-accent-grad-x); }

/* Bars — magnitude over a small ordered set. One bar may take the accent and the rest
   recede: emphasis follows importance, the same rule the status chips follow. */
.helion-bars { display: flex; align-items: flex-end; gap: var(--space-2); height: 120px; }
.helion-bar { flex: 1; border-radius: 6px 6px 0 0; background: var(--chart-muted); min-height: 4px; }
.helion-bar.is-accent { background: var(--helion-accent-grad); }
.helion-bar-labels { display: flex; gap: var(--space-2); margin-top: var(--space-2); }
.helion-bar-labels span { flex: 1; text-align: center; font-size: var(--text-2xs); color: var(--chart-axis); }

/* Donut — parts of a whole, few categories. Rounded caps, track behind. */
.helion-donut { transform: rotate(-90deg); }
.helion-donut circle { fill: none; stroke-linecap: round; }
.helion-donut .helion-donut-track { stroke: var(--chart-track); }

/* Legend — required whenever there are two or more series, so identity is never
   carried by colour alone. Text keeps its own ink; the swatch carries the identity. */
.helion-legend { display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-4); }
.helion-legend-item { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--text-xs); color: var(--helion-muted); }
.helion-legend-swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }

/* Sidebar support link — pinned to the bottom, same shape language as the nav. */
.helion-sidebar-support {
  margin-top: auto; display: flex; align-items: center; gap: 0; flex: none;
  padding: var(--space-3) var(--space-4); margin-left: var(--space-3); margin-right: var(--space-3);
  border-radius: 999px; text-decoration: none; color: var(--helion-nav-muted);
  font-size: var(--text-sm); font-weight: 500;
}
html.helion-sidebar-expanded .helion-sidebar-support { gap: var(--space-3); }
html:not(.helion-sidebar-expanded) .helion-sidebar-support { justify-content: center; }
.helion-sidebar-support:hover { background: var(--helion-nav-raised); color: var(--helion-nav-fg); }

/* Styleguide page only — swatch furniture, not part of the system itself. */
.helion-sg-row { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.helion-sg-swatch {
  width: 56px; height: 44px; border-radius: 10px; flex: none;
  display: inline-flex; align-items: flex-end; justify-content: flex-end;
  padding: var(--space-1); font-size: var(--text-2xs); color: rgba(255,255,255,0.8);
}
.helion-sg-chip {
  min-width: 84px; padding: var(--space-3) var(--space-4); border-radius: var(--helion-radius-sm);
  font-size: var(--text-xs); color: var(--helion-fg); text-align: center;
}
.helion-sg-label { font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--helion-muted); margin: var(--space-5) 0 var(--space-2); font-weight: 600; }

/* --- Chart hover layer --------------------------------------------------------
   A chart in HTML is interactive by default. Two rules from the dataviz spec drive
   this: the hit target must be larger than the painted mark, and the tooltip must
   ENHANCE rather than gate — every value it shows is also reachable without a
   pointer, via keyboard focus and the table view beneath each chart. */

/* Each bar gets a full-height column as its hit target, not just its own painted
   height — a 38% bar is otherwise a sliver to aim at. */
.helion-bar-col {
  flex: 1; height: 100%; display: flex; align-items: flex-end;
  background: none; border: none; padding: 0; cursor: default;
}
.helion-bar-col:hover .helion-bar,
.helion-bar-col:focus-visible .helion-bar { filter: brightness(1.06); }
.helion-bar-col:focus-visible { outline: 2px solid var(--helion-accent); outline-offset: 2px; border-radius: 6px; }
.helion-bars .helion-bar { width: 100%; }

/* Donut: only the stroke is hoverable, and the hovered arc thickens to confirm it. */
.helion-donut circle[data-tip-value] { pointer-events: stroke; cursor: default; }
.helion-donut circle[data-tip-value]:hover,
.helion-donut circle[data-tip-value]:focus-visible { stroke-width: 7.5; outline: none; }

.helion-chart-tip {
  position: fixed; z-index: 400; pointer-events: none;
  transform: translate(-50%, -100%);
  display: flex; flex-direction: column; gap: 1px;
  background: var(--helion-nav); color: #fff;
  padding: var(--space-2) var(--space-3); border-radius: var(--helion-radius-sm);
  white-space: nowrap; opacity: 0;
}
.helion-chart-tip.is-visible { opacity: 1; }
/* Value leads: the reader already knows the series and wants the number. */
.helion-chart-tip-value { font-size: var(--text-base); font-weight: 600; font-variant-numeric: tabular-nums; }
.helion-chart-tip-label { font-size: var(--text-2xs); color: var(--helion-nav-muted); }
@media (prefers-reduced-motion: no-preference) {
  .helion-chart-tip { transition: opacity var(--dur) var(--ease); }
  .helion-bar, .helion-donut circle { transition: filter var(--dur) var(--ease), stroke-width var(--dur) var(--ease); }
}

/* --- Toasts -------------------------------------------------------------------
   Bottom-right, not top-right. Page-level actions live in the top-right of every
   page (Edit company, Add Field, Preview), so a toast there covers the control the
   user is most likely to reach for next — and an error toast, which persists until
   dismissed, would block it indefinitely. The bottom-right corner is clear on every
   page. Rendered outside <main> so it ignores the content column's max-width.

   Meridian has no shadows, so a floating surface is lifted the way every other
   raised control is: card tone plus a hairline. Status is carried by a coloured
   icon rather than by flooding the whole card — a full green panel shouts louder
   than "saved" deserves. */
.helion-toasts {
  position: fixed; z-index: 500; align-items: flex-end;
  bottom: var(--space-5);
  right: var(--space-5);
  width: min(400px, calc(100vw - var(--space-6)));
  display: flex; flex-direction: column; gap: var(--space-2);
  pointer-events: none;   /* the container never blocks the page; toasts re-enable it */
}
.helion-toast {
  pointer-events: auto;
  display: inline-flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4);
  background: var(--helion-toast-bg); color: var(--helion-toast-fg);
  border: none; border-radius: 999px;
  align-self: flex-end;   /* hug the right edge and size to content */
}
/* A glyph inside the status dot, not a bare dot: severity must not rest on colour alone. */
.helion-toast-icon { flex: none; display: inline-flex; width: 17px; height: 17px;
  align-items: center; justify-content: center; border-radius: 999px; color: #fff; }
.helion-toast-icon svg { width: 11px; height: 11px; }
.helion-toast-success .helion-toast-icon { background: var(--helion-chip-success); }
.helion-toast-error .helion-toast-icon { background: var(--helion-chip-attention); }
.helion-toast-body { min-width: 0; font-size: var(--text-sm); color: var(--helion-toast-fg); }
.helion-toast-close {
  flex: none; width: 26px; height: 26px; border: none; cursor: pointer; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 999px; background: var(--helion-toast-close-bg); color: var(--helion-toast-fg); line-height: 0;
}
.helion-toast-close:hover { filter: brightness(1.25); }
.helion-toast-close:focus-visible { outline: 2px solid var(--helion-accent); outline-offset: 1px; }

/* Enters and leaves from the right edge it is anchored to, so the movement explains where it
   came from and where it went. Both directions use the same distance and curve so the exit reads
   as the entrance reversed rather than as a separate effect. Stacked toasts stagger slightly,
   which reads as a sequence instead of one block appearing. */
@media (prefers-reduced-motion: no-preference) {
  .helion-toast { animation: helion-toast-in var(--dur-slow) var(--ease) both; }
  .helion-toast:nth-child(2) { animation-delay: 70ms; }
  .helion-toast:nth-child(3) { animation-delay: 140ms; }
  .helion-toast.is-leaving { animation: helion-toast-out var(--dur) var(--ease) both; }
}
@keyframes helion-toast-in {
  from { opacity: 0; transform: translateX(28px) scale(0.96); }
  to   { opacity: 1; transform: none; }
}
@keyframes helion-toast-out {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translateX(28px) scale(0.96); }
}

/* On narrow screens a toast spans the width under the header rather than hugging a corner. */
@media (max-width: 768px) {
  .helion-toasts { left: var(--space-4); right: var(--space-4); width: auto; bottom: var(--space-4); }
}


/* --- Rich text (Trix) ---------------------------------------------------------

   The Helion layout loads only helion.css, so none of Action Text's own styles
   are present — Trix's stylesheet lives in actiontext.css, which belongs to v1.
   That is deliberate: pulling it in would drag v1's grey borders and 3px radius
   onto a Meridian form. Everything Trix needs is therefore defined here.

   Icons are supplied as mask-image rather than background-image, with the colour
   coming from currentColor. The select chevron bakes its colour into the data URI
   and so needs a second copy for dark mode; masking one set instead means hover,
   active and both themes all fall out of the text colour. */

trix-toolbar { display: block; margin-bottom: var(--space-2); }

trix-toolbar .trix-button-row {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--space-4);
}

trix-toolbar .trix-button-group {
  display: flex; align-items: center; gap: var(--space-1);
  /* Groups are separated by gap alone. Meridian keeps rules for tables, where a
     scannable list needs delineation padding cannot give — a toolbar does not. */
}
trix-toolbar .trix-button-group:empty { display: none; }
trix-toolbar .trix-button-group--file-tools { display: none; }

trix-toolbar .trix-button {
  appearance: none; -webkit-appearance: none;
  position: relative;
  width: 2rem; height: 2rem; padding: 0;
  border: 1px solid transparent; border-radius: var(--helion-radius-sm);
  background: transparent; color: var(--helion-muted);
  cursor: pointer; text-indent: -9999px; overflow: hidden;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              color var(--dur) var(--ease);
}
trix-toolbar .trix-button:hover {
  background: var(--helion-control-bg); border-color: var(--helion-control-edge);
  color: var(--helion-fg);
}
trix-toolbar .trix-button:focus-visible {
  outline: 2px solid var(--helion-accent); outline-offset: 2px;
}
/* Applied formatting is a state, so it follows the same rule as the checkbox
   tiles: the border carries it, the tint supports it. */
trix-toolbar .trix-button.trix-active {
  background: var(--helion-accent-bg); border-color: var(--helion-accent);
  color: var(--helion-accent-strong);
}
trix-toolbar .trix-button:disabled { opacity: 0.4; cursor: not-allowed; }

trix-toolbar .trix-button--icon::before {
  content: ""; position: absolute; inset: 0;
  background-color: currentColor;
  -webkit-mask-image: var(--icon); mask-image: var(--icon);
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-size: 18px 18px; mask-size: 18px 18px;
}

/* The editor itself is a field, so it takes the field treatment. It cannot use
   textarea.helion-input's min-height because trix-editor is not a textarea —
   which is why it came out one line deep. */
trix-editor.helion-input {
  min-height: var(--helion-richtext-min-height);
  height: auto;
}
trix-editor.helion-input:empty::before { color: var(--helion-muted); }
trix-editor.helion-input h1 { font-size: var(--text-xl); margin: 0 0 var(--space-2); }
trix-editor.helion-input blockquote {
  margin: 0 0 var(--space-2); padding-left: var(--space-3);
  border-left: 2px solid var(--helion-border); color: var(--helion-muted);
}
trix-editor.helion-input pre {
  background: var(--helion-tint-bg); border-radius: var(--helion-radius-sm);
  padding: var(--space-2) var(--space-3); font-family: 'IBM Plex Mono', monospace;
  font-size: var(--text-sm); white-space: pre-wrap;
}
trix-editor.helion-input ul, trix-editor.helion-input ol { margin: 0 0 var(--space-2); padding-left: var(--space-5); }
trix-editor.helion-input a { color: var(--helion-accent-strong); }

/* Link dialog — Trix renders it inside the toolbar when you press the link button. */
trix-toolbar .trix-dialogs { position: relative; }
trix-toolbar .trix-dialog {
  position: absolute; top: var(--space-2); left: 0; right: 0; z-index: 5;
  padding: var(--space-3);
  background: var(--helion-card-bg); border: 1px solid var(--helion-border);
  border-radius: var(--helion-radius-sm);
}
trix-toolbar .trix-dialog__link-fields { display: flex; align-items: center; gap: var(--space-2); }
trix-toolbar .trix-dialog__link-fields .trix-input { flex: 1; }
trix-toolbar .trix-input--dialog {
  width: 100%; padding: var(--space-2) var(--space-3);
  border: none; border-radius: var(--helion-input-radius);
  background: var(--helion-input-bg); color: var(--helion-fg);
  font-family: inherit; font-size: var(--text-sm);
}
trix-toolbar .trix-input--dialog:focus { outline: none; background: var(--helion-input-bg-focus); }
trix-toolbar .trix-button--dialog {
  width: auto; height: auto; padding: var(--space-2) var(--space-3);
  text-indent: 0; overflow: visible;
  border: 1px solid var(--helion-control-edge); border-radius: 999px;
  background: var(--helion-control-bg); color: var(--helion-fg);
  font-size: var(--text-sm); font-weight: 500;
}
trix-toolbar .trix-button--dialog:hover { background: var(--helion-control-bg-hover); }

/* Attachment chrome Trix injects into the editor. */
trix-editor .attachment { border-radius: var(--helion-radius-sm); }
trix-editor .attachment__caption { color: var(--helion-muted); font-size: var(--text-xs); }

trix-toolbar .trix-button--icon-bold::before { --icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M7%205v14%22%2F%3E%3Cpath%20d%3D%22M7%205h5.5a3.5%203.5%200%200%201%200%207H7%22%2F%3E%3Cpath%20d%3D%22M7%2012h6.5a3.5%203.5%200%200%201%200%207H7%22%2F%3E%3C%2Fsvg%3E"); }
trix-toolbar .trix-button--icon-italic::before { --icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M15%205h-5%22%2F%3E%3Cpath%20d%3D%22M14%2019H9%22%2F%3E%3Cpath%20d%3D%22M13.5%205l-3%2014%22%2F%3E%3C%2Fsvg%3E"); }
trix-toolbar .trix-button--icon-strike::before { --icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M5%2012h14%22%2F%3E%3Cpath%20d%3D%22M8.5%208.5C8.5%206.5%2010%205%2012%205s3.4%201%203.6%202.6%22%2F%3E%3Cpath%20d%3D%22M15.5%2015.5c-.2%202-1.6%203.5-3.5%203.5s-3.5-1.4-3.5-3.2%22%2F%3E%3C%2Fsvg%3E"); }
trix-toolbar .trix-button--icon-link::before { --icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M10.5%2013.5a4%204%200%200%200%205.7%200l2.3-2.3a4%204%200%201%200-5.7-5.7l-1.3%201.3%22%2F%3E%3Cpath%20d%3D%22M13.5%2010.5a4%204%200%200%200-5.7%200l-2.3%202.3a4%204%200%201%200%205.7%205.7l1.3-1.3%22%2F%3E%3C%2Fsvg%3E"); }
trix-toolbar .trix-button--icon-heading-1::before { --icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M5%205v14%22%2F%3E%3Cpath%20d%3D%22M12%205v14%22%2F%3E%3Cpath%20d%3D%22M5%2012h7%22%2F%3E%3Cpath%20d%3D%22M16.5%2010.5%2019%209v10%22%2F%3E%3C%2Fsvg%3E"); }
trix-toolbar .trix-button--icon-quote::before { --icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M9.5%207.5h-4v4h4c0%202.5-1.2%204-3%204.8%22%2F%3E%3Cpath%20d%3D%22M18.5%207.5h-4v4h4c0%202.5-1.2%204-3%204.8%22%2F%3E%3C%2Fsvg%3E"); }
trix-toolbar .trix-button--icon-code::before { --icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M9%207l-5%205%205%205%22%2F%3E%3Cpath%20d%3D%22M15%207l5%205-5%205%22%2F%3E%3C%2Fsvg%3E"); }
trix-toolbar .trix-button--icon-bullet-list::before { --icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M9%206h11%22%2F%3E%3Cpath%20d%3D%22M9%2012h11%22%2F%3E%3Cpath%20d%3D%22M9%2018h11%22%2F%3E%3Ccircle%20cx%3D%224.5%22%20cy%3D%226%22%20r%3D%221.3%22%20fill%3D%22black%22%20stroke%3D%22none%22%2F%3E%3Ccircle%20cx%3D%224.5%22%20cy%3D%2212%22%20r%3D%221.3%22%20fill%3D%22black%22%20stroke%3D%22none%22%2F%3E%3Ccircle%20cx%3D%224.5%22%20cy%3D%2218%22%20r%3D%221.3%22%20fill%3D%22black%22%20stroke%3D%22none%22%2F%3E%3C%2Fsvg%3E"); }
trix-toolbar .trix-button--icon-number-list::before { --icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M10%206h10%22%2F%3E%3Cpath%20d%3D%22M10%2012h10%22%2F%3E%3Cpath%20d%3D%22M10%2018h10%22%2F%3E%3Cpath%20d%3D%22M4%204.5h1.4v4.2%22%2F%3E%3Cpath%20d%3D%22M4%208.7h2.8%22%2F%3E%3Cpath%20d%3D%22M4%2015.2c0-.8.7-1.3%201.5-1.3s1.4.5%201.4%201.2c0%201.3-2.9%202-2.9%203.6h3%22%2F%3E%3C%2Fsvg%3E"); }
trix-toolbar .trix-button--icon-decrease-nesting-level::before { --icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M9%206h11%22%2F%3E%3Cpath%20d%3D%22M9%2012h11%22%2F%3E%3Cpath%20d%3D%22M9%2018h11%22%2F%3E%3Cpath%20d%3D%22M7%209l-3%203%203%203%22%2F%3E%3C%2Fsvg%3E"); }
trix-toolbar .trix-button--icon-increase-nesting-level::before { --icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M9%206h11%22%2F%3E%3Cpath%20d%3D%22M9%2012h11%22%2F%3E%3Cpath%20d%3D%22M9%2018h11%22%2F%3E%3Cpath%20d%3D%22M4%209l3%203-3%203%22%2F%3E%3C%2Fsvg%3E"); }
trix-toolbar .trix-button--icon-attach::before { --icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M19.5%2011.7l-7.6%207.6a4.4%204.4%200%200%201-6.2-6.2l8.3-8.3a2.9%202.9%200%200%201%204.1%204.1l-8.3%208.3a1.5%201.5%200%200%201-2.1-2.1l7.6-7.6%22%2F%3E%3C%2Fsvg%3E"); }
trix-toolbar .trix-button--icon-undo::before { --icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M4.5%209.5h9.5a4.8%204.8%200%200%201%200%209.5H8%22%2F%3E%3Cpath%20d%3D%22M8.3%205.7%204.5%209.5l3.8%203.8%22%2F%3E%3C%2Fsvg%3E"); }
trix-toolbar .trix-button--icon-redo::before { --icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M19.5%209.5H10a4.8%204.8%200%200%200%200%209.5h6%22%2F%3E%3Cpath%20d%3D%22M15.7%205.7l3.8%203.8-3.8%203.8%22%2F%3E%3C%2Fsvg%3E"); }


/* --- Combobox dropdown --- */

.helion-dropdown { position: absolute; top: 100%; left: 0; right: 0; margin-top: 2px; background: var(--helion-card-bg); border: 1px solid var(--helion-border); border-radius: var(--helion-input-radius, 4px); max-height: 200px; overflow-y: auto; z-index: 200; list-style: none; padding: 0; }
.helion-dropdown li { padding: 0.4rem var(--helion-input-pad-x, 0.75rem); cursor: pointer; font-size: 0.85rem; }
.helion-dropdown li:hover { background: var(--helion-bg); }
.helion-input-disabled { opacity: 0.5; cursor: not-allowed; }


/* Brand colour field — a swatch beside the hex it edits. The swatch is a native colour input
   because it is picking from a continuous space rather than a set, which is the one case the
   combobox convention does not cover. Sized to the field so the two read as one control. */
.helion-brand-field { display: flex; align-items: center; gap: var(--space-3); }
.helion-brand-swatch {
  width: var(--helion-input-min-height); height: var(--helion-input-min-height); flex: none;
  padding: 4px; border: 1px solid var(--helion-control-edge);
  border-radius: var(--helion-input-radius); background: var(--helion-input-bg); cursor: pointer;
}
/* Chrome and Safari each wrap the swatch in their own chrome; without these the colour sits in a
   small inset square with a border of its own rather than filling the control. */
.helion-brand-swatch::-webkit-color-swatch-wrapper { padding: 0; }
.helion-brand-swatch::-webkit-color-swatch { border: none; border-radius: 4px; }
.helion-brand-swatch::-moz-color-swatch { border: none; border-radius: 4px; }
.helion-brand-hex { max-width: 12ch; font-family: 'IBM Plex Mono', monospace; }

/* Jobs index: results beside their filters.
   One column by default and two only when there is room, so the narrow case needs no override —
   the grid collapses, DOM order applies, and the filters sit above the results where a phone
   wants them. The filters are placed into column 2 explicitly rather than reordered, which keeps
   markup order (filters, then results) as the keyboard order in both layouts.

   1180px, not a round number: below it the results column drops under ~800px, and a job card is
   a two-column object — text one side, logo and salary the other — that starts colliding there.
   Above it the cards read better than they did full-width, which is the point of the split. */
.helion-jobs-layout { display: grid; gap: var(--helion-card-gap); align-items: start; }
@media (min-width: 1180px) {
  .helion-jobs-layout { grid-template-columns: minmax(0, 1fr) 340px; }
  .helion-jobs-filters { grid-column: 2; grid-row: 1; }
  .helion-jobs-results { grid-column: 1; grid-row: 1; }
  /* Sticky only in the two-column layout — stacked, the filters are above the results and there
     is nothing to stick to. The offset clears the fixed header plus the page's own top padding,
     so the card settles where it started rather than jumping under the header.

     `align-items: start` on the grid is load-bearing for this: a grid item defaults to stretching
     the row height, and a full-height item has nowhere to travel, so sticky silently does
     nothing. No ancestor may take an overflow other than visible either, for the same reason —
     checked before this was added. */
  .helion-jobs-filters {
    position: sticky;
    top: calc(var(--helion-header-height) + var(--space-5));
    /* Long filter sets should scroll inside rather than run off the bottom of the window. */
    max-height: calc(100vh - var(--helion-header-height) - var(--space-8));
    overflow-y: auto;
  }
  /* The filter grid is auto-fit minmax(190px, 1fr); in a 340px column that resolves to one
     column on its own, so the controls stack without needing to be told to. */
}
/* The card owns the gap below it, so the last thing in each column should not add another. */
.helion-jobs-filters > .helion-card:last-child { margin-bottom: 0; }

/* Company switcher filter. Its own control rather than .helion-input: that is 3rem tall for a
   form field, which is half the dropdown's height before a single company is listed. */
.helion-company-search {
  width: 100%; box-sizing: border-box; margin-bottom: var(--space-1);
  padding: var(--space-2) var(--space-3);
  background: var(--helion-input-bg); border: 1px solid transparent;
  border-radius: var(--helion-radius-sm);
  font-family: inherit; font-size: var(--text-sm); color: var(--helion-fg);
}
.helion-company-search::placeholder { color: var(--helion-muted); }
.helion-company-search:focus-visible { outline: none; border-color: var(--helion-accent-strong); }
.helion-company-empty {
  margin: 0; padding: var(--space-3) var(--space-4);
  font-size: var(--text-sm); color: var(--helion-muted);
}

/* ============================================================================
   ============================================================================
   THE AURORA LAYER
   ----------------------------------------------------------------------------
   Everything above this line is the original Meridian plumbing, kept because
   every component's structure lives in it. Everything below re-skins it.
   This block must stay LAST in the file: at equal specificity it wins on
   source order alone, and moving a rule above what it overrides silently
   un-applies it (that exact failure is documented in the handoff).

   Aurora's own rules, where they differ from Meridian's:
   - Depth is real: layered soft shadows on light, hairline ring + shadow on
     dark. Meridian's "no box-shadows" rule deliberately does not apply here.
   - The accent is the Spectrum sweep: sky #0ea5e9 running to violet #5b4ee0.
     Every gradient call site (focus bar, active tab, pagination, primary
     button) inherits it through --helion-accent-grad / -grad-x.
   - The ground is liquid glass: tinted near-whites drifting hue at almost
     constant lightness, painted once on <body> and fixed, so cards float
     over it. --helion-bg stays a flat colour for the surfaces that need one.
   - Corners are 22 / 16 / 12 px. The three still move together or not at all.
   - The sidebar floats: inset from the edges, fully rounded, glass. The
     active pill is near-black in light mode (inverted in dark) and does NOT
     bleed — the bleed is Meridian's device, retired here via its token.
   - Meters stay THIN. Reference proportions: 3px bars, 5px gaps. Do not
     thicken them for visibility; adjust colour instead.
   ========================================================================== */

/* Inter 4.66, variable — one file per style carries weight 100–900 AND the
   optical-size axis, so large headings automatically take the Display cuts
   (font-optical-sizing defaults to auto). Files must stay NEXT TO this css:
   Propshaft does not rewrite url() across asset roots — same rule as
   Meridian's fonts, documented in the README. */
@font-face { font-family: 'Inter'; font-weight: 100 900; font-style: normal; font-display: swap; src: url("/assets/fonts/inter-var-884c49a1.woff2") format('woff2'); }
@font-face { font-family: 'Inter'; font-weight: 100 900; font-style: italic; font-display: swap; src: url("/assets/fonts/inter-var-italic-0aa7a4b3.woff2") format('woff2'); }

:root {
  /* Type. One family: the variable font's opsz axis is what makes headings
     "Display" — there is no separate Inter Display family to ask for. */
  --aurora-font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --aurora-font-display: var(--aurora-font);

  /* Spectrum accent. --helion-accent stays the brand sky blue; the violet is
     Aurora's own, and the sweep is what carries the pairing. */
  --aurora-violet: #5b4ee0;
  --aurora-mid: #3c78eb;   /* the sweep's midpoint — shadows and halos key off it */
  --aurora-tip-end: #3c78eb;   /* where a heading's ink dissolves to — blue, not violet */
  /* Icon chips: round, neutral GROUND, saturated blue GLYPH — the reference's
     recipe (their violet glyph on a quiet circle). 3.63:1 on the chip, past
     the 3:1 non-text bar. */
  --aurora-chip-bg: #eef0f5;
  --aurora-chip-ink: #3c78eb;
  /* Sub-text label. Deliberately BELOW AA at 3.35:1 — Stephen's explicit
     call (2026-08-17), made knowing the measurement: the reference's own
     grey is 2.64:1 and the paleness is the look. Do not "fix" this back
     to 4.5 without asking him. */
  --aurora-label: #868d97;
  /* Running copy — a step lighter than the UI ink, which is what keeps
     paragraphs from reading heavy beside the airy dashboard. 7.1:1. */
  --aurora-body-ink: #4a515c;
  /* Charts: the VIVID categorical six (Stephen's pick, 2026-08-17) —
     validated with the dataviz validator on Aurora's white AND dark card
     surfaces: worst adjacent colourblind pair deltaE 13.8, worst normal
     pair 20.1, every mark >= 3:1 in BOTH themes from this one set — no
     selected dark steps needed. Order is fixed, never cycled; re-run the
     validator before changing any value. */
  --chart-1: #0b84e0;
  --chart-2: #ea580c;
  --chart-3: #0d9488;
  --chart-4: #8b5cf6;
  --chart-5: #d97706;
  --chart-6: #ec4899;
  /* Sequential rebuilt from the Vivid blue — one hue, light to dark. Dark-
     mode step selection is pending until a real sequential chart exists. */
  --chart-seq-1: #d6e9fb; --chart-seq-2: #9ccaf2; --chart-seq-3: #5ba8e8;
  --chart-seq-4: #0b84e0; --chart-seq-5: #075ea6;
  /* Diverging: the palette's own blue and orange poles, neutral midpoint. */
  --chart-div-low: #0b84e0; --chart-div-mid: #b8bfc9; --chart-div-high: #ea580c;
  --helion-accent-strong: #0673ad;
  --helion-accent-grad: linear-gradient(115deg, var(--helion-accent), var(--aurora-violet));
  --helion-accent-grad-x: linear-gradient(90deg, var(--helion-accent), var(--aurora-violet));
  --helion-accent-halo: rgba(60, 120, 235, 0.22);
  --helion-accent-bg: #e7effc;

  /* Ground + surfaces. Near-white cards over a tinted ground. */
  --helion-bg: #f0f2f7;
  --helion-card-bg: #fcfcfd;
  --helion-tint-bg: #edf0f6;
  --helion-border: #e6e9f0;
  --helion-fg: #101318;
  --helion-muted: #626875;
  --helion-muted-on-page: #5d6370;
  --helion-track: #e2e6ee;
  --helion-heading: #0c1220;

  /* Fields — still recessed, cooler and lighter than Meridian's. */
  --helion-input-bg: #eef1f6;
  --helion-input-bg-hover: #e9edf4;
  --helion-input-bg-focus: #f4f6fa;

  /* Corners. Outer > inner still holds: card 22, secondary 16, field 12. */
  --helion-radius: 22px;
  --helion-radius-sm: 16px;
  --helion-input-radius: 12px;

  /* Depth is TONAL first, shadow second — the reference's layering is three
     surface steps, each lighter as it comes toward you:
       ground (tinted)  <  group card (translucent — the ground breathes
       through it)  <  child tile (near-pure white, carries the soft shadow).
     A shadow on its own does not make depth; parent and child at the same
     tone read as flat whatever the shadow does. That mistake shipped once. */
  --aurora-surface-group: rgba(255, 255, 255, 0.55);
  --aurora-surface-tile: #ffffff;
  /* Shadows: the group's is a whisper; the tile's is the visible lift. */
  --aurora-shadow-group: 0 1px 2px rgba(16, 19, 26, 0.02), 0 10px 30px rgba(16, 19, 26, 0.04);
  --aurora-shadow: 0 1px 2px rgba(16, 19, 26, 0.04), 0 10px 28px rgba(16, 19, 26, 0.07);
  --aurora-shadow-sm: 0 1px 1.5px rgba(16, 19, 26, 0.05), 0 6px 18px rgba(16, 19, 26, 0.06);
  --aurora-glass: rgba(252, 253, 254, 0.72);
  --aurora-glass-edge: rgba(255, 255, 255, 0.65);

  /* Sidebar: light glass rail, dark ink, near-black active pill, no bleed. */
  --helion-nav-fg: #14181f;
  --helion-nav-muted: #5d6470;
  --helion-nav-raised: rgba(16, 19, 24, 0.05);
  --helion-nav-pill: #041324;   /* brand ink navy — same blue as the logo */
  --helion-nav-pill-fg: #ffffff;
  --helion-nav-bleed: 0px;
  --helion-content-gutter: 2.5rem;   /* no bleed to clear any more */

  /* The dark feature surface — brand ink navy, not a neutral near-black:
     the dark group wears the logo's own blue. */
  --helion-hero-bg: #041324;

  /* Stat tiles get depth from shadow now; the corner wash retires. */
  --helion-stat-wash: linear-gradient(transparent, transparent);
}

/* Dark Aurora. Same scale logic, same accent (the sweep is bright enough for
   both grounds); surfaces separate by ring + shadow because there is nowhere
   lighter to go. The active pill inverts to near-white — the toast's logic. */
html.helion-dark {
  --helion-bg: #0c0e13;
  --helion-card-bg: #171a22;
  --helion-tint-bg: #20242e;
  --helion-border: #262b35;
  --helion-fg: #e8eaef;
  --helion-muted: #98a0ac;
  --helion-muted-on-page: #98a0ac;
  --helion-track: #262b35;
  --helion-heading: #f2f4f8;

  --helion-input-bg: #20242e;
  --helion-input-bg-hover: #252a35;
  --helion-input-bg-focus: #1b1f28;

  --helion-accent-bg: #1b2436;

  /* Dark keeps the same three-step logic — group translucent over the glow,
     tile a solid step lighter — with rings doing what shadows cannot. */
  --aurora-surface-group: rgba(30, 34, 45, 0.45);
  --aurora-surface-tile: #1d222d;
  --aurora-shadow-group: 0 0 0 1px rgba(255, 255, 255, 0.03), 0 14px 34px rgba(0, 0, 0, 0.35);
  --aurora-shadow: 0 0 0 1px rgba(255, 255, 255, 0.05), 0 14px 34px rgba(0, 0, 0, 0.5);
  --aurora-shadow-sm: 0 0 0 1px rgba(255, 255, 255, 0.05), 0 6px 16px rgba(0, 0, 0, 0.4);
  --aurora-glass: rgba(20, 23, 30, 0.66);
  --aurora-glass-edge: rgba(255, 255, 255, 0.07);

  --helion-nav-fg: #e8eaef;
  --helion-nav-muted: #8b93a1;
  --helion-nav-raised: rgba(255, 255, 255, 0.06);
  --helion-nav-pill: #e9ebf2;
  --helion-nav-pill-fg: #101318;

  /* Blue reads darker on the dark ground, so the heading tip lifts. */
  --aurora-tip-end: #7aa2f4;
  --aurora-chip-bg: #262b35;
  --aurora-chip-ink: #85a9f0;
  --aurora-label: #79818e;
  --aurora-body-ink: #b3bac4;
  /* The same Vivid six — validated on the dark card too. Declared here so
     Meridian's dark-selected chart steps (still present above in the copied
     block) cannot leak through. */
  --chart-1: #0b84e0; --chart-2: #ea580c; --chart-3: #0d9488;
  --chart-4: #8b5cf6; --chart-5: #d97706; --chart-6: #ec4899;
  --chart-div-low: #0b84e0; --chart-div-mid: #6d7480; --chart-div-high: #ea580c;
  --aurora-body-ink: #b3bac4;

  /* The feature surface must stay distinct from ordinary cards in dark too —
     at the card tone it read as one of them. A violet-tinted lift, one step
     lighter than the cards, keeps it the page's moment of contrast. */
  --helion-hero-bg: #12233c;   /* navy lifted for the dark ground */
  --helion-stat-wash: linear-gradient(transparent, transparent);
}

/* --- Type ------------------------------------------------------------------ */

body { font-family: var(--aurora-font); }
/* Same selector list as Meridian's heading rule above — a bare h2 here loses
   to its `.helion-page-header h2` on specificity, not on order.
   WEIGHT 600, NOT 700: the reference's lightness is mostly this. SF/Inter at
   700 in display sizes reads heavy and "placed"; the polish is semibold with
   tight tracking. Keep every display-size figure at 600 too. */
h1, h2, h3, h4, h5, h6, .helion-auth-title, .helion-card-title, .helion-page-header h2 {
  font-family: var(--aurora-font-display);
  font-weight: 550;   /* variable font — between medium and semibold, the reference's headline weight */
  letter-spacing: -0.02em;
}
/* A group's title is a label for its children, not a headline — the
   reference sets it modest and lets the figures carry the size. */
.helion-card-title { font-size: var(--text-lg); font-weight: 500; }
/* ...but a FORM card has no figures. Nothing else in it carries size, so a modest title leaves the
   card opening at almost the same weight as the label three lines below it and the section never
   announces itself. Scoped to .helion-form so the dashboard keeps the modesty it was given
   deliberately — there the stat figures are the size and the title correctly steps back. */
.helion-form .helion-card-title { font-size: var(--text-xl); font-weight: 550; }
@media (max-width: 768px) { .helion-form .helion-card-title { font-size: var(--text-lg); } }
.helion-company-avatar { font-family: var(--aurora-font); }

/* Gradient-tipped heading — the reference does NOT paint the last word a
   second colour; the heading's own ink DISSOLVES into the violet across
   that word. Ink at the start of the span, violet only by its end — a
   blend, not a split. Wrap only the final word. */
.aurora-grad-text {
  background: linear-gradient(100deg, var(--helion-heading) 0%, var(--aurora-tip-end) 92%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
}

/* --- Ground ---------------------------------------------------------------- */
/* The liquid glass: three chromatic washes at almost the ground's own
   lightness — sky top-left, violet top-right, mint low — over the flat base.
   Painted on a position:fixed ::before layer, NOT background-attachment:
   fixed — that path repaints the whole viewport per scroll frame and left
   visible unpainted bands when tested. A fixed element composites once and
   the page scrolls over it; same picture, none of the artefacts. */

body.helion-app, .helion-auth { background: var(--helion-bg); }
body.helion-app::before, .helion-auth::before {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(55% 60% at 8% -5%, rgba(120, 165, 245, 0.16), transparent 60%),
    radial-gradient(45% 50% at 92% 0%, rgba(150, 122, 240, 0.14), transparent 56%),
    radial-gradient(50% 60% at 75% 108%, rgba(80, 200, 190, 0.10), transparent 60%),
    var(--helion-bg);
}
html.helion-dark body.helion-app::before, html.helion-dark .helion-auth::before {
  background:
    radial-gradient(55% 60% at 8% -5%, rgba(14, 165, 233, 0.10), transparent 60%),
    radial-gradient(45% 50% at 92% 0%, rgba(91, 78, 224, 0.13), transparent 56%),
    radial-gradient(50% 60% at 75% 108%, rgba(45, 160, 150, 0.07), transparent 60%),
    var(--helion-bg);
}

/* --- Depth ----------------------------------------------------------------- */

/* Group surface: translucent, the tinted ground shows through. Stat tiles and
   job cards sit directly on the ground, so they read one step up from it. */
.helion-card, .helion-auth-card, .helion-empty {
  background: var(--aurora-surface-group);
  box-shadow: var(--aurora-shadow-group);
}
.helion-stat, .helion-job { box-shadow: var(--aurora-shadow); }
/* Floating panels stay OPAQUE on purpose — they composite over arbitrary
   content, where translucency renders as a different colour per position. */
.helion-menu-panel, .helion-company-dropdown {
  box-shadow: var(--aurora-shadow);
}
.helion-btn-primary {
  background: linear-gradient(115deg, #0879b8, #5044d6);
  color: #fff;
  box-shadow: 0 6px 16px rgba(60, 120, 235, 0.25);
}

/* --- Header ---------------------------------------------------------------- */
/* No band, no fill — the page is one surface from the top edge down, and the
   header's controls sit directly on the ground. */

.helion-header {
  left: calc(var(--helion-sidebar-current) + 12px);
  background: transparent;
}

/* --- Floating sidebar ------------------------------------------------------ */

.helion-sidebar {
  top: 12px; left: 12px; bottom: 12px;
  border-radius: 26px;
  background: var(--aurora-glass);
  -webkit-backdrop-filter: blur(24px); backdrop-filter: blur(24px);
  border: 1px solid var(--aurora-glass-edge);
  box-shadow: var(--aurora-shadow);
}
.helion-main { margin-left: calc(var(--helion-sidebar-current) + 12px); }

/* White-alpha hovers were tuned against the navy rail; on glass they vanish
   (or glare, in dark). Re-key them to the ink-tint tokens. */
.helion-company-toggle:hover { background: rgba(16, 19, 24, 0.08); }
html.helion-dark .helion-company-toggle:hover { background: rgba(255, 255, 255, 0.1); }

/* The collapsed-rail flyout floated on navy; now it floats on the page — a
   card with the panel shadow, same as every other floating surface. */
html:not(.helion-sidebar-expanded) .helion-nav-children {
  background: var(--helion-card-bg);
  border-radius: var(--helion-radius-sm);
  box-shadow: var(--aurora-shadow);
}

/* Off-canvas on small screens: the floating insets come off so the drawer
   uses the full height, matching Meridian's mobile behaviour. */
@media (max-width: 768px) {
  .helion-sidebar { top: 8px; left: 8px; bottom: 8px; }
  /* Meridian hides the drawer with translateX(-100%), which with an 8px
     left inset leaves an 8px sliver of it peeking at the screen edge —
     the translate must clear the inset too. */
  .helion-sidebar { transform: translateX(calc(-100% - 8px)); }
  html.helion-sidebar-expanded .helion-sidebar { transform: translateX(0); }
  .helion-header { left: 0; }
  .helion-main { margin-left: 0; }
}

/* --- Aurora primitives ----------------------------------------------------- */

/* The AI mark: the sweep in a circle. Sits beside a title wherever a model
   wrote the content — same job as Meridian's gradient ai icon. */
.aurora-ai-mark {
  width: 34px; height: 34px; border-radius: 999px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--helion-accent-grad); color: #fff; font-size: 15px;
  box-shadow: 0 4px 12px rgba(60, 120, 235, 0.35);
}

/* Tally meter — the reference's thin-bar progress mark. 3px bars, 5px gaps,
   THIN IS THE POINT. Set the fraction inline: style="--fill: 62%".
   Track and fill are the same repeating pattern; the fill is the sweep,
   masked to bars, clipped to width. */
.aurora-tally {
  --tally-w: 3px; --tally-gap: 5px;
  position: relative; height: 40px; overflow: hidden;
  background: repeating-linear-gradient(90deg,
    var(--helion-track) 0 var(--tally-w),
    transparent var(--tally-w) calc(var(--tally-w) + var(--tally-gap)));
}
.aurora-tally::before {
  content: ""; position: absolute; inset: 0; width: var(--fill, 0%);
  background: var(--helion-accent-grad-x);
  -webkit-mask-image: repeating-linear-gradient(90deg,
    #000 0 var(--tally-w),
    transparent var(--tally-w) calc(var(--tally-w) + var(--tally-gap)));
  mask-image: repeating-linear-gradient(90deg,
    #000 0 var(--tally-w),
    transparent var(--tally-w) calc(var(--tally-w) + var(--tally-gap)));
}
.aurora-tally-sm { height: 24px; }

/* --- Aurora dashboard ------------------------------------------------------ */
/* The reference's grouping: figures that belong together share ONE parent
   card and sit as layered inner tiles — depth says "these are one subject",
   where Meridian said it with a section label over separate tiles. */

.aurora-dash-grid { display: grid; grid-template-columns: 1.2fr 0.8fr; gap: var(--helion-card-gap); align-items: stretch; margin-bottom: var(--helion-card-gap); }
/* Two peer groups, each with its own children — the reference's side-by-side
   composition rather than one long section. */
.aurora-dash-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--helion-card-gap); align-items: stretch; margin-bottom: var(--helion-card-gap); }
@media (max-width: 980px) { .aurora-dash-grid, .aurora-dash-grid-2 { grid-template-columns: 1fr; } }
.aurora-dash-grid-2 .helion-card { margin-bottom: 0; }

/* Child tiles are BIG — the reference's grouping is a 2×2 of generous cards,
   not a row of small widgets. Two columns, roomy padding, the figure given
   its own band of air below the icon. */
.aurora-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--space-4); }
.aurora-tiles-compact { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
/* A four-tile group is ALWAYS 2x2. auto-fit would happily go three-up on a
   wide screen and widow the fourth tile onto its own row. */
.aurora-tiles-2 { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 480px) { .aurora-tiles-2 { grid-template-columns: 1fr; } }
.aurora-tile {
  position: relative; display: flex; flex-direction: column; justify-content: flex-end;
  /* Near-square. The reference tile is ~1.25:1, and the height IS the
     airiness — the band of empty card between chip and figure is the
     design, not wasted space. Do not shorten these to fit more in. */
  min-height: 188px; text-decoration: none; color: inherit;
  background: var(--aurora-surface-tile); border-radius: var(--helion-radius-sm);
  padding: var(--space-5); box-shadow: var(--aurora-shadow-sm);
}
/* Inner tiles hover by lifting a step, not by changing hue — colour stays
   reserved for the accent and the icon chip. */
a.aurora-tile { transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease); }
a.aurora-tile:hover { transform: translateY(-2px); box-shadow: var(--aurora-shadow); }
a.aurora-tile:focus-visible { outline: 2px solid var(--aurora-mid); outline-offset: 2px; }

.aurora-tile-value {
  display: block; font-family: var(--aurora-font-display);
  font-size: 3rem; font-weight: 200; letter-spacing: -0.02em;   /* 48px thin — the figure is the design */
  font-variant-numeric: tabular-nums; color: var(--helion-fg); line-height: 1.1;
}
.aurora-tile-label { display: block; font-size: var(--text-sm); font-weight: 400; color: var(--aurora-label); margin-top: var(--space-2); }
/* Round, grey, quiet — see the chip tokens. The AI mark is the only chip
   that carries colour. */
.aurora-tile-icon {
  position: absolute; top: var(--space-4); right: var(--space-4);
  width: 44px; height: 44px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--aurora-chip-bg); color: var(--aurora-chip-ink);
}
.aurora-tile-icon svg { width: 20px; height: 20px; }

/* The metric card: one large figure, then AIR, then the thin tally, then the
   caption. The spacing is the design — squeezing these three together is what
   makes a card read as a widget instead of a considered surface. The figure
   goes to the hero size: the card has the room, and a figure that could be
   bigger but isn't reads as placed rather than designed. */
.aurora-metric-value {
  font-family: var(--aurora-font-display); font-size: 5.25rem;   /* the figure is the card */
  font-weight: 200; letter-spacing: -0.03em; line-height: 1;
  font-variant-numeric: tabular-nums; color: var(--helion-fg);
}
.aurora-metric-value .aurora-metric-unit { font-size: var(--text-2xl); font-weight: 500; color: var(--aurora-label); margin-left: 3px; }
.aurora-tally { margin: var(--space-5) 0 var(--space-3); }
.aurora-metric-caption { font-size: var(--text-sm); font-weight: 400; color: var(--aurora-label); }
/* The metric card is the reference's wash-and-inset recipe: a visible
   spectrum wash on the outer card, and a lighter card set INTO it holding
   the figure, meter and caption. Two surfaces inside one card is the
   layering that reads as quality — the wash alone is decoration. */
.aurora-metric-card { display: flex; flex-direction: column; }
.aurora-wash-card {
  background:
    linear-gradient(135deg, rgba(14, 165, 233, 0.20), rgba(91, 78, 224, 0.21) 52%, rgba(80, 200, 190, 0.15)),
    var(--aurora-surface-group);
}
html.helion-dark .aurora-wash-card {
  background:
    linear-gradient(135deg, rgba(14, 165, 233, 0.16), rgba(91, 78, 224, 0.22) 52%, rgba(45, 160, 150, 0.11)),
    var(--aurora-surface-group);
}
.aurora-inset-card {
  background: var(--aurora-surface-tile); border-radius: var(--helion-radius-sm);
  padding: var(--space-5); box-shadow: var(--aurora-shadow-sm);
  margin-top: auto;   /* sits at the card's foot; the wash breathes above it */
}
.aurora-inset-card .aurora-tally { margin: var(--space-4) 0 var(--space-3); }

/* The dark feature card — at most ONE per dashboard; it is the page's moment
   of contrast and a second one halves both. Keyed to --helion-hero-bg, so in
   dark mode it lifts to a ringed card instead of vanishing into the ground. */
.aurora-dark-card {
  background: var(--helion-hero-bg); color: #f4f4f6;
  border-radius: var(--helion-radius); padding: var(--space-4) var(--space-5);
  display: flex; align-items: center; gap: var(--space-4);
  box-shadow: var(--aurora-shadow); margin-bottom: var(--helion-card-gap);
}
html.helion-dark .aurora-dark-card { box-shadow: var(--aurora-shadow); }
.aurora-dark-chip {
  background: rgba(255, 255, 255, 0.1); color: #b8d8fa;
  font-size: var(--text-2xs); font-weight: 600; border-radius: 999px;
  padding: 4px 12px; flex: none; letter-spacing: 0.02em;
}
.aurora-dark-title { font-size: var(--text-base); font-weight: 600; }
.aurora-dark-sub { font-size: var(--text-xs); color: #9aa0ab; margin-top: 1px; }
.aurora-dark-card .helion-btn-primary { margin-left: auto; flex: none; }
@media (max-width: 640px) {
  .aurora-dark-card { flex-wrap: wrap; }
  .aurora-dark-card .helion-btn-primary { margin-left: 0; }
}
/* Grid gap owns the spacing inside the dash grid; the card's own stacking
   margin would double it. */
.aurora-dash-grid .helion-card { margin-bottom: 0; }

/* --- Aurora logo artwork --------------------------------------------------- */
/* The sidebar's <img> tags point at the light-on-navy logo files, which is
   right for Meridian's rail and invisible on Aurora's light glass. Swap the
   rendered artwork for the dark versions (which live next to this css — the
   same Propshaft url() rule as the fonts); dark mode restores the originals. */
.helion-logo-mark { content: url("/assets/aurora/aplify-mark-dark-8e1fa0dc.svg"); }
.helion-logo-full { content: url("/assets/aurora/aplify-dark-9dcf4fca.svg"); }
html.helion-dark .helion-logo-mark,
html.helion-dark .helion-logo-full { content: normal; }

/* A group's title gets real air before its children — the reference's calm is
   mostly this gap. */
.helion-card-title { margin-bottom: var(--space-5); }

/* --- The dark group -------------------------------------------------------- */
/* THE page's dark moment is its primary group — jobs & applications on a
   company's dashboard, Platform on the all-companies view — not an alert
   row. One per page. Children go dark-on-dark with hairline rings; the
   chip glyphs lift to stay readable. */
.aurora-group-dark { background: var(--helion-hero-bg); }
.aurora-group-dark .helion-card-title { color: #f4f5f8; }
.aurora-group-dark .aurora-tile {
  background: rgba(255, 255, 255, 0.055);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.07);
}
.aurora-group-dark a.aurora-tile:hover { background: rgba(255, 255, 255, 0.09); box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1); }
.aurora-group-dark .aurora-tile-value { color: #ffffff; }
.aurora-group-dark .aurora-tile-label { color: rgba(244, 245, 248, 0.62); }
.aurora-group-dark .aurora-tile-icon { background: rgba(255, 255, 255, 0.09); color: #9fc0f8; }

/* --- Feature row ----------------------------------------------------------- */
/* Closing-soon and its kind: a quiet single-row card — chip, line, action.
   Light; the dark treatment belongs to the primary group above. */
.aurora-feature-row { display: flex; align-items: center; gap: var(--space-4); padding: var(--space-4) var(--space-5); }
.aurora-feature-chip {
  background: var(--helion-accent-bg); color: var(--helion-accent-strong);
  font-size: var(--text-2xs); font-weight: 600; border-radius: 999px;
  padding: 4px 12px; flex: none; letter-spacing: 0.02em;
}
.aurora-feature-title { font-size: var(--text-base); font-weight: 550; }
.aurora-feature-sub { font-size: var(--text-xs); font-weight: 400; color: var(--aurora-label); margin-top: 1px; }
.aurora-feature-row .helion-btn-primary { margin-left: auto; flex: none; }
@media (max-width: 640px) {
  .aurora-feature-row { flex-wrap: wrap; }
  .aurora-feature-row .helion-btn-primary { margin-left: 0; }
}

/* --- Header row: heading, user pill, smaller logo -------------------------- */

/* Meridian's active pill widens by --space-3 beyond the bleed token, which
   with the bleed retired ran it into the rail's right edge. Aurora's pill
   stays inside its item. */
.helion-nav-item.active > .helion-nav-link { width: 100%; padding-right: var(--space-4); }

/* The heading and who-you-are sit together; the logo steps down — it is a
   mark in the header now, not a exhibit. */
.aurora-heading-group { display: flex; align-items: center; gap: var(--space-4); min-width: 0; }
.helion-page-header .helion-company-logo-md img { height: 38px; max-width: 160px; }
.aurora-user-pill {
  background: var(--aurora-surface-tile); border-radius: 999px;
  padding: 8px 16px; font-size: var(--text-xs); font-weight: 400;
  color: var(--aurora-label); white-space: nowrap; flex: none;
}
.aurora-user-pill strong { font-weight: 500; color: var(--helion-fg); }

/* --- Search, the reference's way ------------------------------------------- */
/* A compact white pill with the glass inside it — never a full-width field
   with a labelled button. Enter submits. Use this for every search field. */
.aurora-search { position: relative; width: min(300px, 100%); margin-bottom: var(--space-4); }
/* The magnifier is a real submit control: a light grey circle at the pill's
   right end, clickable, not a decoration on the left. */
.aurora-search-btn {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  width: 38px; height: 38px; border-radius: 999px; border: none; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--aurora-chip-bg); color: var(--aurora-label); padding: 0;
}
.aurora-search-btn svg { width: 19px; height: 19px; }
.aurora-search-btn:hover { color: var(--helion-fg); }
.aurora-search-input {
  width: 100%; border: none; border-radius: 999px;
  background: var(--aurora-surface-tile); color: var(--helion-fg);
  padding: 15px 54px 15px 18px; font: inherit; font-size: var(--text-sm);
}
.aurora-search-input::placeholder { color: var(--aurora-label); }
.aurora-search-input:focus { outline: 2px solid var(--aurora-mid); outline-offset: 1px; }

/* --- Tables, the reference's way ------------------------------------------- */
/* The header row is a padded pill band — one continuous rounded surface the
   labels sit in, set in normal case. Rows separate by AIR, not rules: taller,
   no hairlines; the hover tint still says where you are. */
.helion-table { border-collapse: separate; border-spacing: 0; }
.helion-table th {
  background: var(--aurora-surface-tile);
  text-transform: none; letter-spacing: 0;
  font-size: var(--text-sm); font-weight: 500; color: var(--aurora-label);
  padding: 13px var(--space-4);
}
.helion-table th:first-child { border-radius: 999px 0 0 999px; padding-left: var(--space-5); }
.helion-table th:last-child { border-radius: 0 999px 999px 0; padding-right: var(--space-5); }
.helion-table td { border-top: none; height: 64px; padding: var(--space-3) var(--space-4); }
.helion-table td:first-child { padding-left: var(--space-5); }
.helion-table td:last-child { padding-right: var(--space-5); }

/* Status chips: a white pill, a coloured dot, coloured text — the solid
   Signal fills retire in Aurora. Text is the 700-shade of each hue (all
   measured >= 4.5 on the pill); the dot is the vivid shade, which non-text
   marks are allowed. The bare neutral badge keeps NO dot: identity chips
   (category, place, terms) merely describe, and a dot would make every
   label read as a state. */
/* Chips ground on the grey wash, not white: a white pill disappears on a
   white card (job cards, form cards), and a chip must read as a pill on
   EVERY surface it lands on. The wash is the same token the icon chips use. */
.helion-badge {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--aurora-chip-bg); color: var(--helion-muted);
  font-size: var(--text-2xs); font-weight: 550; letter-spacing: 0.01em;
  padding: 0.5em 1em;
}
.helion-badge-success, .helion-badge-attention, .helion-badge-warn, .helion-badge-teal,
.helion-badge-slate, .helion-badge-rose, .helion-badge-violet {
  background: var(--aurora-chip-bg);
}
.helion-badge-success::before, .helion-badge-attention::before, .helion-badge-warn::before,
.helion-badge-teal::before, .helion-badge-slate::before, .helion-badge-rose::before,
.helion-badge-violet::before {
  content: ""; width: 7px; height: 7px; border-radius: 999px; flex: none;
  background: var(--_dot);
}
.helion-badge-success   { color: #15803d; --_dot: #22c55e; }
.helion-badge-attention { color: #b91c1c; --_dot: #ef4444; }
.helion-badge-warn      { color: #a16207; --_dot: #f59e0b; }
.helion-badge-teal      { color: #0f766e; --_dot: #14b8a6; }
/* Slate's dot is deliberately LIGHT: with teal it sat at deltaE 7.3 under
   deuteranopia — the exact teal/slate collapse Meridian's Signal scale hit
   and solved with lightness. #b8c3d1 measures 20.0 against teal, 16.1
   against violet. Re-run the check if either moves. */
.helion-badge-slate     { color: #64748b; --_dot: #b8c3d1; }
.helion-badge-rose      { color: #be123c; --_dot: #f43f5e; }
.helion-badge-violet    { color: #6d28d9; --_dot: #8b5cf6; }
/* Identity carries QUIET TINTS, no dot — the locked system: dots mean
   state; classification is coloured but silent. info = violet (category,
   classification), sky = blue (role). Tints stay readable on the page
   ground too, which is where the neutral wash vanishes. */
.helion-badge-info      { background: #efe9fc; color: #6d28d9; }
.helion-badge-sky       { background: var(--helion-accent-bg); color: #2b64d8; }
html.helion-dark .helion-badge-success   { color: #4ade80; }
html.helion-dark .helion-badge-attention { color: #f87171; }
html.helion-dark .helion-badge-warn      { color: #fbbf24; }
html.helion-dark .helion-badge-teal      { color: #2dd4bf; }
html.helion-dark .helion-badge-slate     { color: #94a3b8; }
html.helion-dark .helion-badge-rose      { color: #fb7185; }
html.helion-dark .helion-badge-violet    { color: #a78bfa; }
html.helion-dark .helion-badge-info      { background: #2a2440; color: #a78bfa; }
html.helion-dark .helion-badge-sky       { background: #1b2436; color: #85a9f0; }

/* --- Card tools row: search beside the primary action ---------------------- */
/* The reference's toolbar: the search pill and any filter pills share the
   header row with the card's one primary action, ranged right. */
.aurora-card-tools { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.aurora-card-tools .aurora-search { margin-bottom: 0; width: 280px; }

/* Air between the header pill band and the first data row. */
.helion-table tbody::before { content: ""; display: table-row; height: 12px; }

/* --- Identity cells -------------------------------------------------------- */
/* A company's row leads with its brand avatar — the switcher's mark, sized
   generously the way the reference draws its people. helion_brand_style
   supplies --brand/--brand-ink; no brand falls back to the accent. */
.aurora-cell-id { display: flex; align-items: center; gap: var(--space-3); font-weight: 500; }
.helion-table .aurora-avatar { width: 42px; height: 42px; font-size: var(--text-base); flex: none; }

/* --- Toggles in the dot-pill language --------------------------------------- */
/* A toggle reads like the chips beside it but must still look PRESSABLE:
   the border is what separates "control" from "label" now that both are
   white pills. On states take the dot + coloured text like the badges. */
.helion-btn-toggle {
  background: var(--aurora-surface-tile); color: var(--helion-muted);
  border: 1px solid var(--helion-border); border-radius: 999px;
  font-size: var(--text-xs); font-weight: 550;
  display: inline-flex; align-items: center; gap: 7px;
}
.helion-btn-toggle.is-on { background: var(--aurora-surface-tile); color: #15803d; border-color: var(--helion-border); }
.helion-btn-toggle.is-on::before { content: ""; width: 7px; height: 7px; border-radius: 999px; flex: none; background: #22c55e; }
.helion-btn-toggle.is-on.is-attention { background: var(--aurora-surface-tile); color: #b91c1c; }
.helion-btn-toggle.is-on.is-attention::before { background: #ef4444; }
.helion-btn-toggle:not(.is-on):hover { background: var(--aurora-chip-bg); }
.helion-btn-toggle.is-on:hover { filter: none; background: var(--aurora-chip-bg); }
html.helion-dark .helion-btn-toggle.is-on { color: #4ade80; }
html.helion-dark .helion-btn-toggle.is-on.is-attention { color: #f87171; }

/* --- Jobs index: toolbar, filter pill, panel ------------------------------- */
[x-cloak] { display: none !important; }

.aurora-toolbar { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-5); }
.aurora-toolbar .aurora-search { margin-bottom: 0; }
.aurora-toolbar .helion-result-count { margin: 0; }
.aurora-toolbar-spacer { flex: 1; }

/* The Filter pill — the reference's funnel-in-a-pill. It TOGGLES the panel
   (type=button, never submit); the count chip says how many filters are
   live, because a panel that closes over active filters is how a list
   quietly shows less than it claims. The panel also opens itself when
   filters are active, same reasoning. */
.aurora-filter-pill {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--aurora-surface-tile); border: none; border-radius: 999px;
  padding: 14px 20px; font: inherit; font-size: var(--text-sm); font-weight: 500;
  color: var(--helion-fg); cursor: pointer;
}
.aurora-filter-pill svg { width: 16px; height: 16px; color: var(--aurora-label); }
.aurora-filter-pill:hover svg { color: var(--helion-fg); }
.aurora-filter-count {
  background: var(--helion-nav-pill); color: var(--helion-nav-pill-fg);
  border-radius: 999px; min-width: 20px; height: 20px; padding: 0 6px;
  font-size: var(--text-2xs); font-weight: 600;
  display: inline-flex; align-items: center; justify-content: center;
}

.aurora-filter-panel { margin-bottom: var(--helion-card-gap); }
.aurora-filter-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--space-4) var(--space-4); }
.aurora-filter-fields .helion-field { margin-bottom: 0; }
.aurora-filter-actions { display: flex; align-items: center; gap: var(--space-4); margin-top: var(--space-5); flex-wrap: wrap; }

/* Results hold a readable measure. Meridian solved the stretched-card
   problem with a permanent filter column; Aurora's filters fold away, so
   the cap is what keeps a card from becoming one very long line. */
.aurora-jobs-results { max-width: 980px; }

/* Job cards sit directly on the ground — tile-white, like everything at
   that depth. */
.helion-job { background: var(--aurora-surface-tile); }

/* --- Fields, system-wide: white pills on tinted grounds -------------------- */
/* The suite rule, from the dashboard work: SURFACES DIP INTO TINT, CONTROLS
   AND FIELDS ARE WHITE PILLS SITTING ON THEM. Meridian's recessed-darker
   field logic (and its gradient focus bar, which cannot sit right inside a
   pill's corner radius) retires in Aurora. Focus is the ring, like the
   search pill. Single-line controls are full pills; a textarea is a
   paragraph, so it takes the soft radius instead. */
.helion-input, .helion-select {
  border-radius: 999px;
  background-color: var(--aurora-surface-tile);
  background-image: none;
  padding: 13px 20px;
}
textarea.helion-input { border-radius: 18px; }
.helion-input::placeholder { color: var(--aurora-label); }
.helion-input:hover, .helion-select:hover { background-color: var(--aurora-surface-tile); }
.helion-input:focus, .helion-select:focus {
  background-color: var(--aurora-surface-tile);
  outline: 2px solid var(--aurora-mid); outline-offset: 1px;
}
/* The select keeps its chevron — and ONLY the chevron; Meridian layered the
   focus bar behind it, which the ring replaces. */
.helion-select { background-image: var(--helion-select-chevron); background-size: auto; }
.helion-select:focus { background-size: auto; }
.helion-combobox-input { padding-right: var(--space-8); }

/* The combobox's list floats like every Aurora panel: white, shadowed,
   soft-cornered, options rounded. */
.helion-combobox-panel {
  background: var(--helion-card-bg); border: none;
  border-radius: var(--helion-radius-sm); box-shadow: var(--aurora-shadow);
  padding: var(--space-2);
}
.helion-combobox-option { border-radius: 12px; }

/* The filter card is the wash-card pattern from the dashboard: tint
   container, white pill fields sitting in it. */
.aurora-filter-card .aurora-search { width: 100%; margin-bottom: var(--space-4); }
.aurora-filter-card .helion-checkbox { margin: var(--space-2) 0 var(--space-4); }

/* --- The description switcher as a segmented pill -------------------------- */
/* AI rewritten / Original / Compare — the reference's segment control: a
   grey-wash track, the active option a white pill lifted out of it.
   Meridian drew this as tabs with the gradient underline; the underline
   retires with the focus bar (same reason — it cannot sit inside a pill). */
.helion-switch {
  display: inline-flex; gap: 2px; align-items: center;
  background: var(--aurora-chip-bg); border-radius: 999px; padding: 4px;
}
.helion-switch label {
  border-radius: 999px; padding: 8px 16px;
  font-size: var(--text-sm); font-weight: 500; color: var(--helion-muted);
  background-image: none; cursor: pointer;
}
.helion-switch input:checked + label {
  background: var(--aurora-surface-tile); color: var(--helion-fg);
  font-weight: 550; box-shadow: var(--aurora-shadow-sm);
  background-image: none;
}
.helion-switch input:focus-visible + label { outline: 2px solid var(--aurora-mid); outline-offset: 1px; }

/* --- Jobs typography ------------------------------------------------------- */
/* Titles join the display register (550, tight); running copy — summaries,
   prose — takes the body ink, a step lighter than UI ink, with looser
   leading. Full heading ink at weight 600 is what read as clunky. */
.helion-job-title { font-family: var(--aurora-font-display); font-weight: 550; letter-spacing: -0.01em; }
.helion-job-summary { color: var(--aurora-body-ink); line-height: 1.6; }
.helion-prose { color: var(--aurora-body-ink); line-height: 1.65; }
.helion-prose h2, .helion-prose h3, .helion-prose h4 { color: var(--helion-fg); }
.helion-detail-layout .helion-prose { font-size: var(--text-base); }

/* --- The wash + inset rule ------------------------------------------------- */
/* WHEREVER the wash gradient grounds a card, its content sits in an inset —
   the dashboard's Live now pattern, now a rule. Two insets: white for
   figures, GLASS for anything holding white pill fields (a white inset
   would swallow them, the same lesson as the chips). */
.aurora-inset-glass {
  background: var(--aurora-surface-group); border-radius: var(--helion-radius-sm);
  padding: var(--space-5);
}
.aurora-filter-card .aurora-inset-glass .helion-field:last-of-type { margin-bottom: var(--space-2); }

/* --- Identity row chips on the page ground --------------------------------- */
/* The grey wash chip disappears on the tinted page ground (the inverse of
   the white-on-white card problem). Neutral and state chips flip to the
   white pill there; the coloured tints already read on both. */
.helion-detail-identity .helion-badge:not(.helion-badge-info):not(.helion-badge-sky) {
  background: var(--aurora-surface-tile);
}

/* --- Owner mark in the details card ---------------------------------------- */
/* The big brand logo leaves the identity row — the mark is a fact about the
   job, so it lives with the facts, small, in the details card header. */
.aurora-details-owner { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); font-weight: 500; }
.aurora-details-owner .helion-company-logo img { height: 22px; max-width: 100px; }

/* --- Wash cards hold their inset close ------------------------------------- */
/* The inset sits 12px from the wash card's edge — the wash is a frame, not
   a field of padding. The heading keeps just enough of its own. */
.aurora-wash-card { padding: 12px; }
.aurora-wash-card > .helion-card-title,
.aurora-wash-card > .helion-card-header,
.aurora-wash-card > form > .helion-card-title { padding: var(--space-3) var(--space-3) 0; margin-bottom: var(--space-4); }
.aurora-wash-card > .helion-card-header .helion-card-title { padding: 0; }

/* --- Job cards open out ---------------------------------------------------- */
/* The fixed 300px figures column packed the card into two squished halves.
   Aurora lets the title, chips and summary run the card's full width, with
   the figures flowing as a meta ROW along the foot — logo, salary, closing
   date — and the actions at the row's right end. The trade is deliberate:
   figures stop lining up down the list, which the reference's cards accept
   for the same openness. */
.helion-job { padding: var(--space-6); row-gap: var(--space-2); }
.helion-job-main { grid-column: 1 / -1; }
.helion-job-aside {
  grid-column: 1; grid-row: 2;
  flex-direction: row; align-items: center; width: auto; text-align: left;
  gap: var(--space-5); margin-top: var(--space-2);
}
.helion-job-actions { grid-column: 2; grid-row: 2; align-self: center; margin-top: var(--space-2); }

/* --- Job card refinements -------------------------------------------------- */
/* The summary holds a reading measure — full card width on a 16" screen is
   a line nobody can track. And it gets air above and below; the meta row
   was sitting on its heels. */
.helion-job-summary { max-width: 74ch; margin: var(--space-5) 0 var(--space-4); }
/* The white logo tile is invisible on the white card, which made the logo
   read as arbitrarily inset — the hairline gives the tile its box back.
   (Meridian ran borderless because its cards were never pure white.) */
.helion-job .helion-company-logo,
.aurora-details-owner .helion-company-logo { border: 1px solid var(--helion-border); }
/* The filter card's glass inset carries slightly less side padding — fields
   are already pills with their own internal air. */
.aurora-filter-card .aurora-inset-glass { padding: var(--space-5) var(--space-4); }

/* --- Meridian stat tiles, re-clothed --------------------------------------- */
/* Fallback pages still render shared/_stat_tile and the stat hero. Rather
   than varianting every such page, the tile itself joins Aurora: white
   tile, neutral round chip, thin figure — and the ENTITY TONE SYSTEM
   RETIRES here (no tone bar, no tone chip): Aurora says identity with
   labels and placement, and reserves colour for state and the accent. */
.helion-stat { background: var(--aurora-surface-tile); background-image: none; }
.helion-stat[data-tone] { padding-left: var(--space-6); }
.helion-stat[data-tone]::after { display: none; }
.helion-stat-icon,
.helion-stat[data-tone] .helion-stat-icon {
  background: var(--aurora-chip-bg); color: var(--aurora-chip-ink);
  width: 44px; height: 44px;
}
.helion-stat-value {
  font-family: var(--aurora-font-display);
  font-weight: 200; letter-spacing: -0.02em; color: var(--helion-fg);
}
.helion-stat-label { font-weight: 400; color: var(--aurora-label); }
/* The hero keeps its navy (the token already moved) and white ink; its
   split figures thin to match. */
.helion-stat-hero .helion-stat-value { color: inherit; }
.helion-stat-split-value { font-weight: 200; }

/* Trix is a paragraph surface wearing .helion-input — it is a custom
   element, not a textarea, so the pill exception missed it and it rendered
   as a giant lozenge. Same soft radius as textareas. */
trix-editor.helion-input { border-radius: 18px; }

/* --- Progress is the tally, everywhere ------------------------------------- */
/* Every proportion in Aurora speaks the Live now language: thin 3px bars,
   5px gaps, the spectrum sweep filling left to right. One look for
   "how far along" wherever it appears — import bars, meters. */
.helion-progress-track {
  height: 30px; border-radius: 0; margin-top: 0;
  background: repeating-linear-gradient(90deg,
    var(--helion-track) 0 3px, transparent 3px 8px);
  overflow: visible;
}
.helion-progress-fill {
  height: 100%; border-radius: 0;
  background: var(--helion-accent-grad-x);
  -webkit-mask-image: repeating-linear-gradient(90deg, #000 0 3px, transparent 3px 8px);
  mask-image: repeating-linear-gradient(90deg, #000 0 3px, transparent 3px 8px);
}
.helion-meter {
  height: 22px; border-radius: 0; overflow: visible;
  background: repeating-linear-gradient(90deg,
    var(--helion-track) 0 3px, transparent 3px 8px);
}
.helion-meter-fill, .helion-meter-fill.is-accent {
  border-radius: 0;
  background: var(--helion-accent-grad-x);
  -webkit-mask-image: repeating-linear-gradient(90deg, #000 0 3px, transparent 3px 8px);
  mask-image: repeating-linear-gradient(90deg, #000 0 3px, transparent 3px 8px);
}
/* The import card wears the full wash recipe (variant partial supplies the
   inset structure); its head sits on the wash like a wash-card title. */
.helion-progress-card.aurora-wash-card { border: none; }
.aurora-wash-card > .helion-progress-head { padding: var(--space-3) var(--space-3) 0; margin-bottom: var(--space-4); }

/* --- Dark card content: definition lists and help text --------------------- */
/* The dark group can hold a facts list (feeds' AI Features card). */
.aurora-group-dark .helion-dl dt { color: rgba(244, 245, 248, 0.55); }
.aurora-group-dark .helion-dl dd { color: #f4f5f8; }
.aurora-group-dark .helion-help-text { color: rgba(244, 245, 248, 0.55); }
.aurora-group-dark .helion-link { color: #9fc0f8; }

/* --- Steps in Aurora's language -------------------------------------------- */
/* The setup strip joins the progress family: the connecting bar is the
   tally (thin bars, spectrum fill), the block is a group card, and undone
   markers are white pills so the strip layers like everything else. Done
   and current keep the sweep — they are the accent meaning "interactive/
   alive", which is its job. */
.helion-steps-block {
  border: none; background: var(--aurora-surface-group);
  box-shadow: var(--aurora-shadow-group);
}
.helion-steps-track, .helion-steps-fill {
  height: 16px; border-radius: 0;
  top: calc(var(--step-dot) / 2 - 8px);
}
.helion-steps-track {
  background: repeating-linear-gradient(90deg,
    var(--helion-track) 0 3px, transparent 3px 8px);
}
.helion-steps-fill {
  background: var(--helion-accent-grad-x);
  -webkit-mask-image: repeating-linear-gradient(90deg, #000 0 3px, transparent 3px 8px);
  mask-image: repeating-linear-gradient(90deg, #000 0 3px, transparent 3px 8px);
}
.helion-step-marker {
  background: var(--aurora-surface-tile);
  box-shadow: var(--aurora-shadow-sm), inset 0 0 0 1px var(--helion-border);
  color: var(--aurora-label);
}
.helion-step-label { font-weight: 500; }
.helion-step-detail { color: var(--aurora-label); }

/* --- Even grid: four cards never widow ------------------------------------- */
/* auto-fit runs 3+1 at mid widths and strands the fourth card. Four, two,
   one — never three. */
.aurora-grid-even { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1280px) { .aurora-grid-even { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 680px) { .aurora-grid-even { grid-template-columns: 1fr; } }

/* --- Step markers, considered ---------------------------------------------- */
/* The gradient dots were Meridian leftovers. Markers speak the chip
   language now: done is a white pill with the success-green check (the
   same green as the status pills beside it), current is the navy moment,
   pending stays quiet, failed is the attention red. The tally line alone
   carries the sweep. */
.helion-step.is-done .helion-step-marker {
  background: var(--aurora-surface-tile); color: #15803d;
  box-shadow: var(--aurora-shadow-sm), inset 0 0 0 1px var(--helion-border);
}
.helion-step.is-current .helion-step-marker {
  background: var(--helion-nav-pill); color: var(--helion-nav-pill-fg);
  box-shadow: 0 0 0 5px rgba(4, 19, 36, 0.1);
}
.helion-step.is-failed .helion-step-marker {
  background: var(--aurora-surface-tile); color: #b91c1c;
  box-shadow: var(--aurora-shadow-sm), inset 0 0 0 1px var(--helion-border);
}
html.helion-dark .helion-step.is-done .helion-step-marker { color: #4ade80; }
html.helion-dark .helion-step.is-current .helion-step-marker { box-shadow: 0 0 0 5px rgba(233, 235, 242, 0.15); }
html.helion-dark .helion-step.is-failed .helion-step-marker { color: #f87171; }

/* --- Cards that hold facts, not lists -------------------------------------- */
/* A round icon chip beside the title says what the card is about before a
   word is read; hairlines pace the rows; values step up to 500 so the
   answer outweighs its label. */
.aurora-card-title-icon { display: flex; align-items: center; gap: var(--space-3); }
.aurora-card-icon {
  width: 34px; height: 34px; border-radius: 999px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--aurora-chip-bg); color: var(--aurora-chip-ink);
}
.aurora-card-icon svg { width: 16px; height: 16px; }
.helion-dl dt { border-top: 1px solid var(--helion-border); padding-top: var(--space-3); margin-top: var(--space-3); }
.helion-dl dt:first-of-type { border-top: none; padding-top: 0; margin-top: 0; }
.helion-dl dd { font-weight: 500; }
/* Chips inside a facts value wrap with air instead of colliding. */
.helion-dl dd .helion-badge, .helion-detail-value .helion-badge { margin: 2px 6px 2px 0; }

/* --- Three-across rows ----------------------------------------------------- */
.aurora-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--helion-card-gap); margin-bottom: var(--helion-card-gap); align-items: stretch; }
@media (max-width: 1024px) { .aurora-grid-3 { grid-template-columns: 1fr; } }
.aurora-grid-3 .helion-card { margin-bottom: 0; }

/* A stat as its own card: tile anatomy at card scale. */
.aurora-stat-card { position: relative; display: flex; flex-direction: column; justify-content: flex-end; min-height: 180px; }
/* Hairlines inside the dark card are alpha-white, not the light border
   token, which glares on navy. */
.aurora-group-dark .helion-dl dt { border-color: rgba(255, 255, 255, 0.12); }

/* The switcher avatar's fallback ink (the all-companies ∗ and unbranded
   companies) is white — Meridian's on-accent navy was tuned for its flat
   blue and clashes on the sweep, worst in dark. A branded company's
   computed ink arrives via --brand-ink and is untouched. */
.helion-company-avatar { color: var(--brand-ink, #ffffff); }

/* --- Bars, the reference's way --------------------------------------------- */
/* Each column is a full-height soft well; the value is a rounded fill
   rising from its foot — white with a hairline (so it reads on the well),
   the emphasised bar in the sweep. The reference's Activity chart. */
.helion-bars { align-items: stretch; height: 150px; gap: var(--space-2); }
.helion-bar-col {
  flex: 1; display: flex; align-items: flex-end;
  background: var(--aurora-chip-bg); border-radius: 14px;
  border: none; padding: 0; cursor: pointer; overflow: hidden;
}
.helion-bar {
  width: 100%; border-radius: 14px; min-height: 10px;
  background: var(--aurora-surface-tile);
  box-shadow: inset 0 0 0 1px var(--helion-border);
}
/* The emphasised bar is ONE hue blending vertically — soft at the crown,
   deepening to the chart blue at its foot (the reference's treatment) —
   not the two-hue brand sweep, which belongs to interactive fills. */
.helion-bar.is-accent { background: linear-gradient(180deg, #c3e0fa 0%, #0b84e0 85%); box-shadow: none; }
html.helion-dark .helion-bar { background: #323947; box-shadow: none; }
