/* ==========================================================================
   Highline Payments 2.0 — base
   Reset, typography, accessibility primitives and motion defaults.

   Colours, radii and shadows are NEVER written literally in this project's
   stylesheets. Every one is a --hl-* custom property emitted by ThemeService
   from the admin-managed theme settings, so the palette is changed in one
   place. Sizes, spacing and durations come from tokens.css. The only literal
   values below are the token FALLBACKS, which exist purely so the CSS is still
   readable — and the error/maintenance pages still render — if opened without
   the application layer.
   ========================================================================== */

*,
*::before,
*::after { box-sizing: border-box; }

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
    /* Sticky header offset for in-page anchor links. */
    scroll-padding-top: calc(var(--hl-header-height, 4.5rem) + var(--hl-space-lg, 2rem));
}

body {
    margin: 0;
    background: var(--hl-bg, #fff);
    color: var(--hl-text, #12142e);
    font-family: var(--hl-font-body, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);
    font-size: var(--hl-size-body, 1rem);
    line-height: var(--hl-leading-body, 1.65);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
    /* Nothing may cause a horizontal scrollbar; artwork that breaks out of its
       container is clipped here rather than widening the page. */
    overflow-x: hidden;
}

img, svg, video, canvas { display: block; max-width: 100%; }
img, video { height: auto; }

h1, h2, h3, h4, h5, h6 {
    margin: 0 0 0.5em;
    font-family: var(--hl-font-heading, inherit);
    font-weight: var(--hl-weight-bold, 700);
    line-height: var(--hl-leading-heading, 1.14);
    letter-spacing: var(--hl-tracking-heading, -0.022em);
    text-wrap: balance;
}

p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

a { color: var(--hl-primary, #2a2d7c); text-decoration-thickness: 1px; text-underline-offset: 0.2em; }
a:hover { color: var(--hl-accent, #cf2927); }

ul, ol { margin: 0 0 1em; padding-left: 1.25em; }

button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }

hr { border: 0; border-top: 1px solid var(--hl-border, #e3e5f0); margin: var(--hl-space-lg, 2rem) 0; }

/* --- Focus -----------------------------------------------------------------
   A visible focus ring on every interactive element. :focus-visible keeps it
   off for mouse users without ever removing it for keyboard users. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline: 3px solid var(--hl-accent, #cf2927);
    outline-offset: 2px;
    border-radius: 2px;
}

/* On a dark environment the accent ring alone can sit too close to the
   background; a light outer ring guarantees the contrast either way. */
.hl-on-dark :where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline-color: var(--hl-text-on-dark, #f5f6fb);
    box-shadow: 0 0 0 6px rgba(var(--hl-accent-rgb, 207, 41, 39), 0.45);
}

/* --- Accessibility helpers ------------------------------------------------- */
.hl-sr-only {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.hl-skip-link {
    position: absolute;
    top: -100%;
    left: var(--hl-space-sm, 1rem);
    z-index: var(--hl-z-skip, 1000);
    padding: var(--hl-space-xs, 0.75rem) var(--hl-space-md, 1.5rem);
    background: var(--hl-primary, #2a2d7c);
    color: #fff;
    border-radius: var(--hl-radius-md, 12px);
    text-decoration: none;
    font-weight: var(--hl-weight-semibold, 600);
}
.hl-skip-link:focus { top: var(--hl-space-sm, 1rem); color: #fff; }

/* --- Typography scale ------------------------------------------------------
   The nine roles from the design system. Each is a class so a heading can carry
   the right SEMANTIC level (§35: one logical H1, correct H2/H3 order) while
   taking whatever VISUAL weight the composition needs — the two must never be
   forced to agree. */

.hl-display {
    font-size: var(--hl-size-display, 4rem);
    line-height: var(--hl-leading-display, 0.98);
    letter-spacing: var(--hl-tracking-display, -0.035em);
    font-weight: var(--hl-weight-bold, 700);
    max-width: var(--hl-measure-display, 18ch);
}

.hl-h1 {
    font-size: var(--hl-size-h1, 3rem);
    line-height: var(--hl-leading-tight, 1.06);
    letter-spacing: var(--hl-tracking-display, -0.035em);
    max-width: var(--hl-measure-heading, 26ch);
}

.hl-h2 {
    font-size: var(--hl-size-h2, 2.25rem);
    line-height: var(--hl-leading-heading, 1.14);
    max-width: var(--hl-measure-heading, 26ch);
}

.hl-h3 {
    font-size: var(--hl-size-h3, 1.5rem);
    line-height: var(--hl-leading-snug, 1.35);
    letter-spacing: var(--hl-tracking-snug, -0.012em);
}

.hl-h4 {
    font-size: var(--hl-size-h4, 1.25rem);
    line-height: var(--hl-leading-snug, 1.35);
    letter-spacing: var(--hl-tracking-snug, -0.012em);
}

/* A centred heading's measure has to be released or it sits off-centre. */
.hl-text-center :where(.hl-display, .hl-h1, .hl-h2, .hl-lead),
:where(.hl-display, .hl-h1, .hl-h2).hl-text-center {
    margin-inline: auto;
}

.hl-lead {
    font-size: var(--hl-size-body-lg, 1.25rem);
    line-height: var(--hl-leading-snug, 1.35);
    color: var(--hl-text-muted, #5a5f7a);
    max-width: var(--hl-measure-lead, 58ch);
    text-wrap: pretty;
}

/* NAME COLLISION, deliberately guarded: the page shell is <body class="hl-body">
   (see layouts/public.php), so an unqualified `.hl-body { max-width }` sets a
   68ch READING MEASURE on the whole document and squeezes the entire site into
   a ~620px column. The measure is a typographic role and only ever belongs on a
   text element, never on the shell — hence :not(body). The font-size is safe on
   both: the `body` rule above already sets the same value. */
.hl-body { font-size: var(--hl-size-body, 1rem); }
.hl-body:not(body) { max-width: var(--hl-measure-body, 68ch); }
.hl-body-sm { font-size: var(--hl-size-body-sm, 0.9375rem); }
.hl-small { font-size: var(--hl-size-small, 0.875rem); }

/* Section label. Set in a colour the caller chooses via --hl-eyebrow-color so
   the same component works on light and dark without a variant class. */
.hl-eyebrow {
    display: flex;
    align-items: center;
    gap: var(--hl-space-2xs, 0.5rem);
    margin: 0 0 var(--hl-space-sm, 1rem);
    font-size: var(--hl-size-eyebrow, 0.78125rem);
    font-weight: var(--hl-weight-bold, 700);
    letter-spacing: var(--hl-tracking-eyebrow, 0.16em);
    line-height: 1.2;
    text-transform: uppercase;
    color: var(--hl-eyebrow-color, var(--hl-accent, #cf2927));
}

/* A short lead rule reads as a signal entering the label rather than as
   decoration — the payment-infrastructure idea at the smallest possible scale. */
.hl-eyebrow::before {
    content: "";
    flex: 0 0 auto;
    width: var(--hl-space-md, 1.5rem);
    height: 2px;
    background: currentColor;
    border-radius: var(--hl-radius-pill, 999px);
}

.hl-eyebrow--plain::before { display: none; }
.hl-eyebrow--center { justify-content: center; }

.hl-legal, .hl-disclaimer {
    margin-top: var(--hl-space-md, 1.5rem);
    font-size: var(--hl-size-legal, 0.8125rem);
    line-height: var(--hl-leading-snug, 1.35);
    color: var(--hl-text-muted, #5a5f7a);
    max-width: var(--hl-measure-body, 68ch);
}

/* Accent a single word or phrase inside a heading without changing its weight. */
.hl-accent-text { color: var(--hl-accent, #cf2927); }

/* Rich text from the CMS. Scoped so editor markup can never restyle the page. */
.hl-rich > :first-child { margin-top: 0; }
.hl-rich > :last-child { margin-bottom: 0; }
.hl-rich h2, .hl-rich h3, .hl-rich h4 { margin-top: 1.5em; }
.hl-rich ul, .hl-rich ol { padding-left: 1.35em; }
.hl-rich li + li { margin-top: 0.35em; }
.hl-rich blockquote {
    margin: 1.5em 0;
    padding: 0.25em 0 0.25em 1.25em;
    border-left: 3px solid var(--hl-accent, #cf2927);
    color: var(--hl-text-muted, #5a5f7a);
    font-style: italic;
}
.hl-rich table { width: 100%; border-collapse: collapse; margin: 1.5em 0; }
.hl-rich th, .hl-rich td {
    padding: 0.6em 0.8em;
    border-bottom: 1px solid var(--hl-border, #e3e5f0);
    text-align: left;
}
.hl-rich th { font-weight: var(--hl-weight-bold, 700); }

/* --- Dark environments -----------------------------------------------------
   One class flips the text tokens for a whole subtree, so a component written
   once works on both backgrounds instead of needing a `--dark` variant. */
.hl-on-dark {
    color: var(--hl-text-on-dark, #f5f6fb);
    --hl-text: var(--hl-text-on-dark, #f5f6fb);
    --hl-text-muted: var(--hl-text-on-dark-muted, rgba(245, 246, 251, 0.66));
    --hl-border: var(--hl-hairline-on-dark, rgba(245, 246, 251, 0.12));
    --hl-surface: var(--hl-surface-dark, #12142e);
}

.hl-on-dark a { color: var(--hl-text-on-dark, #f5f6fb); }
.hl-on-dark a:hover { color: var(--hl-accent-light, #e24543); }
.hl-on-dark .hl-lead { color: var(--hl-text-on-dark-muted, rgba(245, 246, 251, 0.66)); }


/* --- Animation defaults ----------------------------------------------------
   Elements marked data-hl-reveal start invisible ONLY once JavaScript has
   confirmed it can animate them (it sets .hl-anim-ready on <html>). Without
   that class the content is simply visible — so a script error, a slow parse
   or a blocked module never hides real copy from a visitor or a crawler. */
/* --- Scroll-reveal vocabulary ----------------------------------------------
   A SMALL, deliberate set of reveals (§29) — not one fade-up applied to
   everything. Each has a job:

     fade         copy that should not move (long paragraphs, legal)
     fade-up      the default for a block entering
     rise         large headings: a longer, softer lift
     mask         heading wipe — the text is revealed, never created
     slide-left / slide-right   horizontal reveals for split layouts
     draw         network lines drawing themselves (stroke-dashoffset)
     activate     a node lighting up (scale + glow, no displacement)
     scale-in     product/hardware artwork arriving
     counter      handled by JS; the final value is already in the DOM

   THE INVERSION RULE, and it is not negotiable: targets are visible by default.
   The hidden state only applies under .hl-anim-ready, which animations.js adds
   to <html> once it has CONFIRMED it can animate. A script error, a blocked
   module or an old browser therefore leaves every word visible to a visitor and
   to a crawler. Never write a hidden default here. */
[data-hl-reveal],
[data-hl-stagger] > * {
    opacity: 1;
    transform: none;
}

.hl-anim-ready :where([data-hl-reveal], [data-hl-stagger] > *) {
    opacity: 0;
    will-change: opacity, transform;
}

/* Default and explicit fade-up share the vertical offset. */
.hl-anim-ready :where([data-hl-reveal=""], [data-hl-reveal="fade-up"]),
.hl-anim-ready [data-hl-stagger] > * {
    transform: translate3d(0, var(--hl-anim-distance, 28px), 0);
}

.hl-anim-ready [data-hl-reveal="fade"] { transform: none; }
.hl-anim-ready [data-hl-reveal="rise"] { transform: translate3d(0, calc(var(--hl-anim-distance, 28px) * 1.6), 0); }
.hl-anim-ready [data-hl-reveal="slide-left"]  { transform: translate3d(calc(var(--hl-anim-distance, 28px) * -1.5), 0, 0); }
.hl-anim-ready [data-hl-reveal="slide-right"] { transform: translate3d(calc(var(--hl-anim-distance, 28px) *  1.5), 0, 0); }
.hl-anim-ready [data-hl-reveal="scale-in"] { transform: scale(0.94) translate3d(0, calc(var(--hl-anim-distance, 28px) * 0.5), 0); }
.hl-anim-ready [data-hl-reveal="activate"] { transform: scale(0.82); }

/* Heading mask: the glyphs are real text in the DOM, clipped by their own line
   box. The reveal slides the text up inside the clip — nothing is generated,
   so the heading is still selectable and crawlable while hidden. */
[data-hl-reveal="mask"] {
    display: inline-block;
    clip-path: inset(-0.18em 0 -0.18em 0);
}

.hl-anim-ready [data-hl-reveal="mask"] {
    opacity: 1;
    clip-path: inset(-0.18em 0 100% 0);
    transform: translate3d(0, 0.5em, 0);
}

.hl-anim-ready [data-hl-reveal="mask"].hl-revealed {
    clip-path: inset(-0.18em 0 -0.18em 0);
    transition: clip-path var(--hl-duration-reveal, 760ms) var(--hl-ease-emphasis, cubic-bezier(0.16, 1, 0.3, 1)),
                transform var(--hl-duration-reveal, 760ms) var(--hl-ease-emphasis, cubic-bezier(0.16, 1, 0.3, 1));
}

/* Line drawing for inline SVG network paths. The dash length is set by JS from
   the path's own measured length, so this works at any scale. */
.hl-anim-ready [data-hl-reveal="draw"] {
    opacity: 1;
    stroke-dasharray: var(--hl-draw-length, 1000);
    stroke-dashoffset: var(--hl-draw-length, 1000);
}

.hl-anim-ready [data-hl-reveal="draw"].hl-revealed {
    stroke-dashoffset: 0;
    transition: stroke-dashoffset var(--hl-duration-reveal, 760ms) var(--hl-ease-in-out, cubic-bezier(0.65, 0, 0.35, 1));
}

/* Applied by animations.js when an element has finished revealing, and used as
   the no-GSAP fallback path. */
.hl-revealed {
    opacity: 1 !important;
    transform: none !important;
    transition: opacity var(--hl-duration-reveal, 760ms) var(--hl-ease-emphasis, cubic-bezier(0.16, 1, 0.3, 1)),
                transform var(--hl-duration-reveal, 760ms) var(--hl-ease-emphasis, cubic-bezier(0.16, 1, 0.3, 1));
}

/* mask and draw animate a property other than transform; the shared rule above
   would otherwise cancel their reveal. */
.hl-revealed:where([data-hl-reveal="mask"], [data-hl-reveal="draw"]) {
    transform: none !important;
}

/* --- Reduced motion --------------------------------------------------------
   Everything still renders; only the movement stops. */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }

    *,
    *::before,
    *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }

    .hl-anim-ready :where([data-hl-reveal], [data-hl-stagger] > *) {
        opacity: 1 !important;
        transform: none !important;
        clip-path: none !important;
        stroke-dashoffset: 0 !important;
    }
}

/* --- Print ----------------------------------------------------------------- */
@media print {
    .hl-header, .hl-footer, .hl-to-top, .hl-announce, .hl-modal, .hl-loader { display: none !important; }
    body { color: #000; background: #fff; }
}
