/*
 * Postsale brand skin.
 *
 * Two things live here: the palette and type the renderer draws itself with, and the header bar this page puts
 * above it.
 *
 * A plain stylesheet rather than the renderer's `customCss` option, and with no `!important` anywhere, because the
 * renderer ships its own theme inside `@layer scalar-theme` — and unlayered CSS beats a layer whatever the
 * specificity. Everything below is unlayered, so one `:root` declaration replaces a themed value. (`init.js` still
 * uses `customCss` for the two rules that fight the renderer's *own* utility classes, where that reasoning does not
 * apply.)
 *
 * Colours are Postsale's, read out of postsale.com's stylesheet and the app's `ui/src/ui-component/Logo.tsx` rather
 * than sampled off a screenshot: the teal is the logo's own #3ad1b0, the near-black navies are the marketing site's
 * `--color-dark-*` scale, and the greys are its `--color-gray-*`. Every hex below is one of those tokens, so when
 * the brand moves this file can be re-derived instead of re-eyeballed.
 */

/* ============================================================================================================
   Palette
   ============================================================================================================

   Dark is the bare `body` and light is `body.light-mode`, rather than a pair of matched classes, because the
   renderer stamps `light-mode`/`dark-mode` on <body> only once it has booted, and the header is ours and paints
   before that. Dark is the right thing to show in that gap — postsale.com has no light mode at all.

   On <body> rather than `:root` because that is the element the renderer's own theme declares these on, and a
   custom property set on an element is not something a value inherited from its parent can outrank — layers do
   not enter into it. Declaring on the same element is what makes these win. */

body {
    /* Surfaces: dark-900 for the page, dark-800 for anything raised off it (cards, code, request panels),
       dark-700 for hover and table headers. dark-600 is one step lighter again so borders stay visible against
       all three, which they would not if the border matched the hover fill. */
    --scalar-background-1: #0a0f1a;
    --scalar-background-2: #111827;
    --scalar-background-3: #1a2744;
    --scalar-background-card: #111827;
    --scalar-border-color: #243356;

    /* Not pure white: the marketing site sets body copy well below #fff and the pages here are long enough that
       the difference is felt. gray-100 and gray-400 for the first two tiers, at 17.4:1 and 7.4:1.

       The third is the one off-token value in this file, and deliberately. gray-500 (#6a7282) is the next step
       down and lands at 3.96:1 here, under AA for the placeholder and disabled text this drives — and gray-400 is
       already taken by the tier above, so the scale has nothing between them to reach for. This is the two of
       them averaged per channel, 5.5:1: three distinct tiers, and still re-derivable if the scale moves. */
    --scalar-color-1: #f3f4f6;
    --scalar-color-2: #99a1af;
    --scalar-color-3: #828a98;

    /* teal-400, the logo disc. ~10:1 on the page background, so it can carry link text and not just decoration. */
    --scalar-color-accent: #3ad1b0;
    --scalar-background-accent: #3ad1b01f;

    /* The renderer tints method badges and status pills from these. Postsale's own scale, picked one shade
       brighter than the marketing site's defaults because these sit on navy rather than on white. */
    --scalar-color-green: #00c758;
    --scalar-color-blue: #54a2ff;
    --scalar-color-orange: #ffb96d;
    --scalar-color-red: #ff6568;
    --scalar-color-yellow: #ffd236;
    --scalar-color-purple: #c07eff;

    /* postsale.com's `--primary`/`--primary-foreground`: teal fill, near-black label. Every button on the
       marketing site is this pair. */
    --scalar-button-1: #00c0a0;
    --scalar-button-1-color: #040712;
    --scalar-button-1-hover: #14b899;

    /* dark-950, a step below the page. Header and sidebar share it, so the chrome reads as one surface with the
       content sitting in a well between them — the same arrangement as the app. */
    --scalar-sidebar-background-1: #040712;
    --scalar-sidebar-border-color: #1a2744;
    --scalar-sidebar-color-1: var(--scalar-color-1);
    --scalar-sidebar-color-2: var(--scalar-color-2);
    --scalar-sidebar-color-active: var(--scalar-color-accent);
    --scalar-sidebar-item-hover-background: #111827;
    --scalar-sidebar-item-hover-color: var(--scalar-color-1);
    --scalar-sidebar-item-active-background: var(--scalar-background-accent);
    --scalar-sidebar-search-background: #0a0f1a;
    --scalar-sidebar-search-border-color: #1a2744;
}

body.light-mode {
    --scalar-background-1: #ffffff;
    --scalar-background-2: #f9fafb;
    --scalar-background-3: #f3f4f6;
    --scalar-background-card: #ffffff;
    --scalar-border-color: #e5e7eb;

    --scalar-color-1: #101828;
    --scalar-color-2: #4a5565;
    --scalar-color-3: #6a7282;

    /* teal-700, not the logo's teal-400. #3ad1b0 on white is 1.9:1 — fine as a disc, unreadable as text. teal-700
       is the darkest step that still reads as the brand and the first that clears 4.5:1 (5.5:1). */
    --scalar-color-accent: #107665;
    --scalar-background-accent: #14b8991f;

    --scalar-color-green: #00a544;
    --scalar-color-blue: #155dfc;
    --scalar-color-orange: #f05100;
    --scalar-color-red: #e40014;
    --scalar-color-yellow: #cd8900;
    --scalar-color-purple: #8200da;

    /* postsale.com's own light shell: `--background` off-white for the chrome, `--border` grey for its edge. */
    --scalar-sidebar-background-1: #fcfcfc;
    --scalar-sidebar-border-color: #e5e5e5;
    --scalar-sidebar-item-hover-background: #f3f4f6;
    --scalar-sidebar-search-background: #ffffff;
    --scalar-sidebar-search-border-color: #e5e5e5;
}

/* ============================================================================================================
   Type and shape
   ============================================================================================================

   `:root` here, where the palette above is `body`, and the difference is not arbitrary: these are the tokens the
   renderer itself declares on `:root`, and the palette is what it declares on `body`. The rule the palette block
   states — same element, or the value is only inherited and loses — decides which block a new token belongs in.
   Check where the renderer declares it before adding one. */

:root {
    /* Inter and Geist Mono are what postsale.com loads. Neither is fetched here — the page is built to make no
       third-party request at all, and self-hosting two variable faces is a lot of bytes for a difference most
       readers will not see. Named first so anyone who has them gets them, with the platform UI stack behind. */
    --scalar-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    --scalar-font-code: 'Geist Mono', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;

    /* The renderer's default base is 3px, which reads as a different product. postsale.com ships one radius token,
       `--radius: .625rem`, so 10px is the brand's card corner; 6px is that scaled down for the badges and inputs
       the base is also applied to.

       All three are pinned because the renderer derives the rest of its scale off the base —
       `min(calc(var(--scalar-radius) * n), var(--scalar-radius-max))`, n of 2 for `-lg` and 8/3 for `-xl`. Setting
       the base alone would put `-lg` at 12px, past the brand's own 10. `-2xl` and `-3xl` are left to derive. */
    --scalar-radius: 6px;
    --scalar-radius-lg: 10px;
    --scalar-radius-xl: 12px;
}

/* ============================================================================================================
   Landing page
   ============================================================================================================

   Scoped to `.introduction-section`, which is the renderer's own name for it, so no operation page is touched —
   and unlayered `display: none` is enough, no `!important`, unlike the rules in init.js. */

/* The column holding the introduction card — Server, Authentication, Client Libraries — which gives the section
   the full width rather than half of it beside an empty half.

   The column rather than the card: hiding the card alone leaves its column reserving the space, which is the whole
   problem. This supersedes hiding the card, so init.js no longer does. */
.introduction-section .section-column:has(> .sticky-cards) {
    display: none;
}

/* A ceiling rather than a reading measure, and deliberately so. 92rem is 1472px, which is wider than the content
   area of a laptop — so on the screens most readers are on this is simply full width, and the cap only engages on
   a display wide enough that the alternative is a line running the length of a desk.

   Not the ~107 characters the two-column layout used to give this prose, which is what a measure would be. The
   page is meant to fill; this only stops it filling without limit. */
.introduction-section .markdown > * {
    max-width: 92rem;
}

.introduction-section .markdown > table {
    max-width: 100%;
}

/* `fit-content` as well as the cap, because a code block is a filled box: left to stretch, a one-line
   `Authorization:` example becomes a metre of empty background. This way it takes the room it needs and no more,
   up to the full width when the sample is genuinely long. Not applied to the table — `fit-content` there collapses
   the columns rather than fitting them. */
.introduction-section .markdown > pre {
    width: fit-content;
    max-width: 100%;
}

/* ============================================================================================================
   Key handoff notice
   ============================================================================================================

   Built by `showNotice` in init.js: once when the app hands this page a key, and once more on the reload that
   removing one performs. Fixed rather than placed in the flow, so it costs no layout — a bar in the document
   would have to be added to `--scalar-custom-header-height`, and that value is load-bearing for the renderer's
   sticky sidebar. This floats over the page instead, and nothing already on it moves. */

.ps-key-banner {
    position: fixed;
    /* Centred under the header rather than beside it: `--ps-header-height` is the one offset that keeps this clear
       of the bar, and centring by transform rather than by `left: 0; right: 0` keeps the box its content's width
       instead of the viewport's. */
    top: calc(var(--ps-header-height) + 12px);
    left: 50%;
    transform: translateX(-50%);
    /* Above the header (20) so it is never tucked behind it, below the search modal, which is z-10000. */
    z-index: 30;
    display: flex;
    align-items: flex-start;
    gap: 10px;
    /* 30rem holds the longer of the two messages on two lines at the base font size. The viewport fallback is the
       16px inset doubled, so the box keeps its margins on a phone instead of running to the edges. */
    max-width: min(30rem, calc(100vw - 32px));
    /* Even, except on the left, where the 8px dot plus this gap has to leave the text on the same optical margin
       as the padding gives it everywhere else. */
    padding: 12px 12px 12px 14px;
    /* Accent-tinted edge over the raised surface rather than the accent itself: this is a notice, not a call to
       action, and a solid teal panel would outrank the operation a reader is trying to read. */
    border: 1px solid color-mix(in srgb, var(--scalar-color-accent) 40%, transparent);
    border-radius: var(--scalar-radius-lg);
    background: var(--scalar-background-2);
    /* The renderer's own raised-panel shadow, so this sits at the same height as its cards rather than at one
       invented for it. The only value in this file that would otherwise have been a raw colour. */
    box-shadow: var(--scalar-shadow-2);
    font-family: var(--scalar-font);
}

/* The one accent mark, carrying "this worked" so the words do not have to. */
.ps-key-banner::before {
    content: '';
    flex: none;
    width: 8px;
    height: 8px;
    margin-top: 7px;
    border-radius: 999px;
    background: var(--scalar-color-accent);
}

.ps-key-banner__message {
    margin: 0;
    color: var(--scalar-color-2);
    font-size: 13px;
    line-height: 1.5;
}

/* The gap after the bold clause is set here rather than as a leading space in the string, where it would be
   invisible to anyone reading or editing the message. */
.ps-key-banner__message strong {
    margin-right: 0.25em;
    color: var(--scalar-color-1);
    font-weight: 600;
}

/* The real action, so it looks like one. Bordered rather than filled: it undoes something, and a solid accent
   button would read as the thing to do next. */
.ps-key-banner__remove {
    flex: none;
    align-self: center;
    padding: 5px 10px;
    border: 1px solid var(--scalar-border-color);
    border-radius: var(--scalar-radius);
    background: none;
    color: var(--scalar-color-1);
    font-family: inherit;
    font-size: 12px;
    font-weight: 500;
    white-space: nowrap;
    cursor: pointer;
}

.ps-key-banner__remove:hover {
    border-color: var(--scalar-color-accent);
    color: var(--scalar-color-accent);
}

.ps-key-banner__dismiss {
    flex: none;
    padding: 0 4px;
    border: 0;
    background: none;
    color: var(--scalar-color-3);
    font-size: 18px;
    line-height: 1.2;
    cursor: pointer;
}

.ps-key-banner__dismiss:hover {
    color: var(--scalar-color-1);
}

/* ============================================================================================================
   Header
   ============================================================================================================ */

/* Two names for one number because they have different owners. `--ps-header-height` is ours and is what the header
   below is laid out from; `--scalar-custom-header-height` is the renderer's hook for being told how much of the
   viewport is already spoken for, which is what keeps its sticky sidebar and mobile header pinned below the bar
   rather than under it. Aliasing sets the height in one place, and lets the renderer's name change under us
   without any of the header's own rules moving. */
:root {
    --ps-header-height: 56px;
    --scalar-custom-header-height: var(--ps-header-height);
}

.ps-header {
    position: sticky;
    top: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 12px;
    box-sizing: border-box;
    height: var(--ps-header-height);
    /* Left is 6px, not 16px, because the brand link carries 6px of its own: the mark then starts at the same 12px
       inset as the sidebar's search box directly below it. */
    padding: 0 16px 0 6px;
    background: var(--scalar-sidebar-background-1);
    border-bottom: 1px solid var(--scalar-sidebar-border-color);
    font-family: var(--scalar-font);
}

.ps-brand {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 4px 6px;
    border-radius: var(--scalar-radius);
    color: var(--scalar-color-1);
    text-decoration: none;
}

.ps-brand:hover {
    background: var(--scalar-sidebar-item-hover-background);
}

.ps-brand__mark {
    display: block;
    width: 26px;
    height: 26px;
}

/* Height-driven, width auto: the viewBox is cropped to the lettering, so its 4.41:1 ratio does the sizing. 17px of
   box is about 13px of visible letter — the rest is the `p`'s descender. */
.ps-brand__wordmark {
    display: block;
    width: auto;
    height: 17px;
}

/* Echoes the pill above the headline on postsale.com: accent text, accent-tinted rule, faint accent fill. */
.ps-header__label {
    padding: 4px 9px;
    border: 1px solid color-mix(in srgb, var(--scalar-color-accent) 32%, transparent);
    border-radius: 999px;
    background: var(--scalar-background-accent);
    color: var(--scalar-color-accent);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
}

.ps-header__nav {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-left: auto;
}

.ps-header__nav a {
    padding: 7px 11px;
    border-radius: var(--scalar-radius);
    color: var(--scalar-color-2);
    font-size: 13px;
    font-weight: 500;
    text-decoration: none;
    white-space: nowrap;
}

.ps-header__nav a:hover {
    background: var(--scalar-sidebar-item-hover-background);
    color: var(--scalar-color-1);
}

/* Fully rounded, teal, dark label — the same button postsale.com puts in this corner. */
.ps-header__nav a.ps-header__cta {
    padding: 7px 15px;
    border-radius: 999px;
    background: var(--scalar-button-1);
    color: var(--scalar-button-1-color);
    font-weight: 600;
}

.ps-header__nav a.ps-header__cta:hover {
    background: var(--scalar-button-1-hover);
    color: var(--scalar-button-1-color);
}

/* Narrow screens: the lockup and the one link that leads somewhere useful survive; the rest is decoration and the
   sidebar's own toggle needs the room. */
@media (max-width: 640px) {
    .ps-header {
        gap: 8px;
        padding-right: 10px;
    }

    .ps-header__label,
    .ps-header__nav a:not(.ps-header__cta) {
        display: none;
    }
}
