/* ===========================================================================
   Kestrel website - token layer.

   The colour, radius and font tokens below are lifted verbatim from
   kestrel-platform/resources/css/kestrel.css, which is the authoritative
   Kestrel design system. Somebody who signs in from this site must not feel
   they have arrived at a different product, so nothing here invents a colour.

   What this file ADDS to the app's tokens is only what a marketing surface
   needs and an application does not: a display type scale, a wider shell, and
   a section rhythm. The app is 13px and dense because it is read all day; this
   site is 16px and open because it is read once.
   =========================================================================== */

:root {
    color-scheme: light;

    /* --- surfaces and ink. Verbatim from the platform. */
    --ks-canvas: #f6f5f3;
    --ks-surface: #ffffff;
    --ks-raised: #fbfaf9;
    --ks-sunken: #f2f0ed;
    --ks-border: #e8e5e0;
    --ks-border-strong: #dcd8d2;
    --ks-text: #20263a;
    --ks-text-muted: #5d657c;
    --ks-accent: #ec6a4c;
    --ks-ink: #2b3358;
    --ks-danger: #b83a30;
    --ks-info: #2b6cb0;

    /* --- THE FOUR TOKENS THIS SITE DARKENS, AND WHY.
       The platform's values are #8b91a4, #1f8a5f, #a5720d and #c5453a. In the
       application they carry 12 to 13px labels inside a dense grid where the
       row, the icon and the position already say what the colour is saying.
       Here the same colours carry meaning on their own: a 12px mono operation
       key, a job state, a rate, an inline form error. Measured against
       --ks-canvas and against the faint tints this site sets them on, all four
       come out below 4.5:1, which fails WCAG AA at those sizes. The values
       below clear it with margin left over, and they are the same hues.
       Dark mode needs only one of the four moved, and only by a step:
       --ks-text-subtle goes from #828a99 to #8a92a1, because #828a99 on
       --ks-raised measures 4.49:1 and the route header and the footer both put
       a small label there. */
    --ks-text-subtle: #656c81;
    --ks-success: #177049;
    --ks-warning: #8a5f0b;

    /* --- accent, in its two jobs.
       --ks-accent is the brand vermilion, and it is used for FILLS AND TINTS
       whose meaning does not depend on contrast: the mark's chip, a tag's
       background, a chip on the route, an indicator rule that is paired with a
       weight and a background change.
       --ks-accent-ink is the same hue taken deep enough to be TEXT and to be a
       filled surface under white text. On --ks-canvas it is 5.5:1, white on it
       is 6.0:1, and it still clears AA over a 12 per cent tint of itself. Every
       accent-coloured word, every focus ring and every primary button uses this
       one, because at 3.1:1 the brand vermilion is not a text colour however
       much one would like it to be. */
    --ks-accent-ink: #b03c19;
    --ks-on-accent-ink: #ffffff;

    /* The one token the app does not need: a filled slab that carries the
       brand mark's own colour at page scale. The app never paints a whole
       panel in --ks-ink, so it has no name for it. In dark mode it resolves to
       a raised surface instead, because ink is a TEXT tone there and a panel
       painted with it would invert the page. */
    --ks-slab: #262d4e;
    --ks-slab-line: #3d456b;
    --ks-on-slab: #f4f2ef;
    --ks-on-slab-muted: #b9bed6;

    --ks-shadow-1: 0 1px 2px rgba(32, 38, 58, .05), 0 1px 3px rgba(32, 38, 58, .04);
    --ks-shadow-2: 0 4px 16px rgba(32, 38, 58, .07), 0 1px 3px rgba(32, 38, 58, .05);
    --ks-shadow-3: 0 18px 48px rgba(32, 38, 58, .10), 0 2px 6px rgba(32, 38, 58, .05);

    /* --- shape. One scale, followed everywhere. No pills. */
    --ks-radius-sm: 6px;
    --ks-radius-md: 8px;
    --ks-radius: 10px;
    --ks-radius-lg: 12px;
    --ks-radius-xl: 16px;

    /* --- type */
    --ks-font: 'Plus Jakarta Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
    --ks-font-mono: 'JetBrains Mono', ui-monospace, 'SFMono-Regular', 'Cascadia Mono', monospace;

    /* Marketing display scale. Ratios chosen so the hero headline is two lines
       at every width from 360px up, which is what keeps it inside the first
       viewport without a font-size override per breakpoint. */
    --step-display: clamp(2.5rem, 5.6vw, 4.35rem);
    --step-title: clamp(1.875rem, 3.6vw, 2.85rem);
    --step-heading: clamp(1.375rem, 2.1vw, 1.6rem);
    --step-subheading: clamp(1.0625rem, 1.4vw, 1.1875rem);
    --step-lead: clamp(1.0625rem, 1.25vw, 1.1875rem);
    --step-body: 1rem;
    --step-small: .875rem;
    /* Both raised one step. --step-meta was .75rem and --step-micro .6875rem,
       which is where an operation key, a scope, a rate and a job state were
       being set. At 11px those had stopped being read and started being
       texture, which is the point at which technical detail turns into
       decoration. 13px and 12px keep the density and give the labels back
       their job. */
    --step-meta: .8125rem;
    --step-micro: .75rem;

    /* --- shell. Wider than the app's 1440px content column would suggest,
       because the app column holds tables and this one holds a headline. */
    --shell: 1280px;
    --gutter: clamp(1.25rem, 4.2vw, 3rem);
    /* Was clamp(4.5rem, 8.5vw, 8rem). Sized for a homepage carrying twice as
       much as it does now; at 8rem the shortened sections read as adrift
       rather than as spacious. */
    --section-y: clamp(3.5rem, 5.8vw, 5.75rem);
    --rule: 1px solid var(--ks-border);

    --ease: cubic-bezier(.22, 1, .36, 1);
    --ease-out: cubic-bezier(.16, 1, .3, 1);
}

/* Dark values, verbatim from the platform's [data-theme="dark"] block. Two
   rules rather than one so an explicit choice wins over the system in both
   directions: :root[data-theme="dark"] and the system query guarded against an
   explicit light choice. */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme='light']) {
        color-scheme: dark;
        --ks-canvas: #0e1014;
        --ks-surface: #171a21;
        --ks-raised: #1f242c;
        --ks-sunken: #282e38;
        --ks-border: #2d333d;
        --ks-border-strong: #414954;
        --ks-text: #f0f2f7;
        --ks-text-muted: #aeb5c3;
        --ks-text-subtle: #8a92a1;
        --ks-accent: #f4795b;
        --ks-accent-ink: #f4795b;
        --ks-on-accent-ink: #14161b;
        --ks-ink: #c8cee6;
        --ks-success: #57c894;
        --ks-warning: #e2ae45;
        --ks-danger: #f08a7d;
        --ks-info: #78b2e8;
        --ks-slab: #1c212a;
        --ks-slab-line: #333a46;
        --ks-on-slab: #f0f2f7;
        --ks-on-slab-muted: #aeb5c3;
        --ks-shadow-1: 0 1px 2px rgba(0, 0, 0, .5);
        --ks-shadow-2: 0 12px 34px rgba(0, 0, 0, .62), 0 2px 8px rgba(0, 0, 0, .45);
        --ks-shadow-3: 0 22px 60px rgba(0, 0, 0, .66), 0 2px 8px rgba(0, 0, 0, .45);
    }
}

:root[data-theme='dark'] {
    color-scheme: dark;
    --ks-canvas: #0e1014;
    --ks-surface: #171a21;
    --ks-raised: #1f242c;
    --ks-sunken: #282e38;
    --ks-border: #2d333d;
    --ks-border-strong: #414954;
    --ks-text: #f0f2f7;
    --ks-text-muted: #aeb5c3;
    --ks-text-subtle: #8a92a1;
    --ks-accent: #f4795b;
    --ks-accent-ink: #f4795b;
    --ks-on-accent-ink: #14161b;
    --ks-ink: #c8cee6;
    --ks-success: #57c894;
    --ks-warning: #e2ae45;
    --ks-danger: #f08a7d;
    --ks-info: #78b2e8;
    --ks-slab: #1c212a;
    --ks-slab-line: #333a46;
    --ks-on-slab: #f0f2f7;
    --ks-on-slab-muted: #aeb5c3;
    --ks-shadow-1: 0 1px 2px rgba(0, 0, 0, .5);
    --ks-shadow-2: 0 12px 34px rgba(0, 0, 0, .62), 0 2px 8px rgba(0, 0, 0, .45);
    --ks-shadow-3: 0 22px 60px rgba(0, 0, 0, .66), 0 2px 8px rgba(0, 0, 0, .45);
}

/* ------------------------------------------------------------------ baseline */

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

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
    /* Every in-page target clears the sticky header. Without this an anchor
       lands with its heading hidden behind the bar. */
    scroll-padding-top: 6rem;
}

body {
    margin: 0;
    background: var(--ks-canvas);
    color: var(--ks-text);
    font-family: var(--ks-font);
    font-size: var(--step-body);
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
    /* No horizontal scrollbar can be introduced by a wide child, and no
       section is allowed to rely on this instead of fixing its own overflow. */
    overflow-x: clip;
}

h1,
h2,
h3,
h4,
p,
figure,
blockquote,
dl,
dd {
    margin: 0;
}

ul,
ol {
    margin: 0;
    padding: 0;
    list-style: none;
}

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

a {
    color: inherit;
    text-decoration: none;
}

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

code,
kbd,
samp,
pre {
    font-family: var(--ks-font-mono);
    font-size: .9em;
}

[hidden] {
    display: none !important;
}

/* Focus is visible on every interactive element, in the accent, at the same
   offset, in both themes. Nothing on this site removes an outline. */
:focus-visible {
    outline: 2px solid var(--ks-accent-ink);
    outline-offset: 3px;
    border-radius: var(--ks-radius-sm);
}

::selection {
    background: color-mix(in oklab, var(--ks-accent) 24%, transparent);
    color: var(--ks-text);
}

/* The surfaces the browser draws and no design system owns. Untouched, the
   caret is black in a navy-inked page and every scroll container ships the
   platform's own grey. */
html {
    scrollbar-color: var(--ks-border-strong) transparent;
}

input,
textarea {
    caret-color: var(--ks-accent-ink);
}

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

.shell {
    width: 100%;
    max-width: var(--shell);
    margin-inline: auto;
    padding-inline: var(--gutter);
}

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

/* Skip link: off-screen until focused, then a real control at the top left. */
.skip {
    position: fixed;
    top: .75rem;
    left: .75rem;
    z-index: 200;
    transform: translateY(-200%);
    background: var(--ks-surface);
    color: var(--ks-text);
    border: 1px solid var(--ks-border-strong);
    border-radius: var(--ks-radius-md);
    padding: .625rem 1rem;
    font-size: var(--step-small);
    font-weight: 700;
    box-shadow: var(--ks-shadow-2);
    transition: transform .18s var(--ease-out);
}

.skip:focus-visible {
    transform: translateY(0);
}

.mono {
    font-family: var(--ks-font-mono);
    font-variant-ligatures: none;
    font-feature-settings: 'ss02' off;
}

/* ------------------------------------------------------------------- buttons */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    min-height: 2.875rem;
    padding: .6875rem 1.25rem;
    border: 1px solid transparent;
    border-radius: var(--ks-radius-md);
    background: transparent;
    font-size: var(--step-small);
    font-weight: 700;
    letter-spacing: -.005em;
    line-height: 1.2;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color .16s var(--ease), border-color .16s var(--ease),
        transform .16s var(--ease), box-shadow .16s var(--ease), color .16s var(--ease);
}

.btn:active {
    transform: translateY(1px);
}

.btn--primary {
    background: var(--ks-accent-ink);
    border-color: var(--ks-accent-ink);
    /* White on the brand vermilion is 3.1:1 and fails AA at every size on this
       button. On --ks-accent-ink it is 5.1:1. */
    color: var(--ks-on-accent-ink);
    box-shadow: var(--ks-shadow-1);
}

.btn--primary:hover {
    background: color-mix(in oklab, var(--ks-accent-ink) 88%, #000);
    border-color: color-mix(in oklab, var(--ks-accent-ink) 88%, #000);
    box-shadow: var(--ks-shadow-2);
}

.btn--secondary {
    background: var(--ks-surface);
    border-color: var(--ks-border-strong);
    color: var(--ks-text);
    box-shadow: var(--ks-shadow-1);
}

.btn--secondary:hover {
    background: var(--ks-raised);
    border-color: var(--ks-text-subtle);
}

.btn--ghost {
    color: var(--ks-text-muted);
}

.btn--ghost:hover {
    background: var(--ks-sunken);
    color: var(--ks-text);
}

.btn--onslab {
    background: transparent;
    border-color: color-mix(in oklab, var(--ks-on-slab) 48%, transparent);
    color: var(--ks-on-slab);
}

.btn--onslab:hover {
    background: color-mix(in oklab, var(--ks-on-slab) 12%, transparent);
    border-color: color-mix(in oklab, var(--ks-on-slab) 52%, transparent);
}

.btn--sm {
    min-height: 2.25rem;
    padding: .4375rem .875rem;
    font-size: var(--step-meta);
}

.btn--lg {
    min-height: 3.125rem;
    padding: .8125rem 1.5rem;
    font-size: var(--step-body);
}

/* A text link that reads as an action. The rule grows from the left rather
   than fading in, so the affordance is legible without colour. */
.link {
    display: inline-flex;
    align-items: baseline;
    gap: .375rem;
    color: var(--ks-text);
    font-weight: 700;
    font-size: var(--step-small);
    background-image: linear-gradient(var(--ks-accent-ink), var(--ks-accent-ink));
    background-repeat: no-repeat;
    background-position: 0 100%;
    background-size: 0 2px;
    transition: background-size .22s var(--ease-out), color .16s var(--ease);
}

.link:hover,
.link:focus-visible {
    background-size: 100% 2px;
    color: var(--ks-accent-ink);
}

.link__arrow {
    color: var(--ks-accent-ink);
    transition: transform .22s var(--ease-out);
}

.link:hover .link__arrow {
    transform: translateX(3px);
}

/* -------------------------------------------------------------------- badges */

.tag {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    padding: .1875rem .4375rem;
    border-radius: var(--ks-radius-sm);
    border: 1px solid color-mix(in oklab, var(--tone, var(--ks-text-muted)) 26%, transparent);
    background: color-mix(in oklab, var(--tone, var(--ks-text-muted)) 12%, transparent);
    color: var(--tone, var(--ks-text-muted));
    font-family: var(--ks-font-mono);
    font-size: var(--step-micro);
    font-weight: 500;
    line-height: 1.35;
    white-space: nowrap;
}

.tag--accent {
    --tone: var(--ks-accent-ink);
}

.tag--plain {
    border-color: var(--ks-border);
    background: var(--ks-sunken);
    color: var(--ks-text-muted);
}

/* The brand mark. Three strokes, drawn in templates/partials/mark.php, sized
   here so a caller changes one custom property rather than the SVG's width and
   height attributes. --mark-size is the optical square the K sits in. */
.mark {
    --mark-size: 24px;
    width: var(--mark-size);
    height: var(--mark-size);
    flex: none;
    overflow: visible;
}

.mark__ink {
    stroke: var(--ks-ink);
}

.mark__accent {
    stroke: var(--ks-accent);
}

/* One colour, for a single-ink print or a monochrome context. Both strokes
   take the inherited colour and the K stays whole. */
.mark--mono .mark__ink,
.mark--mono .mark__accent {
    stroke: currentColor;
}

.mark--lg {
    --mark-size: 40px;
}

/* ---------------------------------------------------------- reduced motion */

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }

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

/* An anchor has to land below whatever is stuck to the top of the viewport.
   Most pages have only the 68px header; the four with an on-page subnav have
   another 46px of it. :has() lets the document ask which kind of page it is
   rather than every page declaring it. */
html:has(.subnav) {
    scroll-padding-top: 8.75rem;
}
