/* =============================================================================
   AbuseScore components
   =============================================================================

   The component layer. tokens.css defines the surface ramp, the scales and the
   motion vocabulary; effects.css builds the MagicUI effect set on top of it;
   this file assembles both into the actual furniture of the site.

   Three rules run through everything here:

     1. Nothing is flat. Every surface that is meant to sit above the page
        carries a hairline, an inner top highlight and an inner bottom lip.
        A rectangle of a slightly different colour is not a card.
     2. Depth comes from light, not from drop shadows. On a dark ground a drop
        shadow only deepens what is behind an element. What makes it read as
        raised is the edge catching light along the top.
     3. Recessed things exist. Inputs, code wells and meters are cut into the
        page, not laid on it. A design with only "page" and "card" always looks
        flat because nothing is ever below the surface.

   The class hooks are the documented set in docs/theming.md plus the
   marketing, legal and app-shell furniture listed in theme.php.
   ========================================================================== */

/* -----------------------------------------------------------------------------
   Reset and base
   -------------------------------------------------------------------------- */

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

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
    scroll-padding-top: calc(var(--nav-height) + 16px);
}

body {
    margin: 0;
    min-height: 100vh;
    background: var(--surface-page);
    color: var(--text);
    font-family: var(--sans);
    font-size: 17px;
    line-height: 1.65;
    font-weight: 400;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: hidden;
}

/* The ambient wash behind everything. Two coloured lights and a very faint
   vignette, so the dark never reads as a dead fill. */
body::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: -2;
    pointer-events: none;
    background:
        radial-gradient(1100px 620px at 82% -12%, rgba(61, 220, 132, .13), transparent 62%),
        radial-gradient(860px 520px at 4% -6%, rgba(67, 208, 255, .08), transparent 64%),
        radial-gradient(1200px 900px at 50% 120%, rgba(169, 124, 248, .06), transparent 70%);
}

/* Grain over the wash. Large gradients on a dark page band badly, and the
   banding is most of what makes a gradient look cheap. */
body::after {
    content: '';
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    opacity: .35;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.3'/%3E%3C/svg%3E");
}

/* The weight ramp. 700 is loaded; using 600 for everything wastes it and
   leaves every heading looking like the same heading. */
h1, h2, h3, h4, h5, h6 {
    margin: 0 0 .5em;
    line-height: 1.15;
    letter-spacing: -.025em;
    color: var(--text);
}
h1 { font-weight: 700; letter-spacing: -.035em; }
h2 { font-weight: 700; letter-spacing: -.03em; }
h3 { font-weight: 600; }
h4, h5, h6 { font-weight: 600; letter-spacing: -.015em; }

p { margin: 0 0 1em; }

a {
    color: var(--signal-ink);
    text-decoration-color: rgba(61, 220, 132, .35);
    text-underline-offset: 3px;
    transition: color var(--t-fast) var(--ease-out),
                text-decoration-color var(--t-fast) var(--ease-out);
}
a:hover { color: #6fe9a8; text-decoration-color: currentColor; }

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

hr { border: 0; border-top: 1px solid var(--line); margin: var(--space-6) 0; }

img, svg { max-width: 100%; height: auto; }

::selection { background: rgba(61, 220, 132, .28); color: #fff; }

:focus-visible {
    outline: 2px solid var(--signal-ink);
    outline-offset: 3px;
    border-radius: 4px;
}

/* Scrollbar, so the chrome does not stay light grey on a dark page. */
* { scrollbar-width: thin; scrollbar-color: var(--chrome) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
    background: var(--chrome);
    border-radius: 999px;
    border: 3px solid transparent;
    background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover { background: var(--chrome-hover); background-clip: padding-box; }

.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 200;
    background: var(--signal);
    /* A fixed dark ink, not `--surface-page`.
     *
     * The green fill is the brand green in both themes and does not move, so
     * the text on it must not either. Pointing it at the page colour meant the
     * light palette painted near-white on mid-green at 1.63:1: the first thing
     * a keyboard user reaches on every page, unreadable. */
    color: #07120c;
    padding: .65rem 1.1rem;
    border-radius: 0 0 var(--radius-sm) 0;
    font-weight: 700;
}
.skip-link:focus { left: 0; top: 0; }

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

/* -----------------------------------------------------------------------------
   Shell
   -------------------------------------------------------------------------- */

.layout { display: flex; flex-direction: column; min-height: 100vh; }

.layout__main {
    flex: 1 0 auto;
    width: 100%;
    max-width: var(--shell-max);
    margin: 0 auto;
    padding: 0 var(--space-5) var(--space-9);
}

/* The auth shell. This class was being emitted with nothing behind it, which
   is why the sign-in card used to sit in the top left corner of a wide page. */
.layout__main--centered {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    max-width: 100%;
    min-height: 100vh;
    padding: var(--space-7) var(--space-5);
}

.layout--auth { position: relative; }

/* A pair of drifting lights behind the auth card, so the narrow shell is not a
   card floating in nothing. */
.auth-foot {
    margin: var(--space-5) 0 0;
    font-size: .85rem;
    color: var(--text-dim);
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    justify-content: center;
}
.auth-foot a { color: var(--text-muted); text-decoration: none; }
.auth-foot a:hover { color: var(--signal-ink); }

.layout--auth::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background:
        radial-gradient(620px 420px at 50% 8%, rgba(61, 220, 132, .16), transparent 66%),
        radial-gradient(520px 380px at 12% 92%, rgba(67, 208, 255, .10), transparent 68%);
}

/* -----------------------------------------------------------------------------
   Header
   -------------------------------------------------------------------------- */

.site-header {
    position: sticky;
    top: 0;
    z-index: 60;
    background: var(--surface-veil);
    backdrop-filter: blur(16px) saturate(160%);
    -webkit-backdrop-filter: blur(16px) saturate(160%);
    border-bottom: 1px solid var(--line);
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .05), 0 1px 0 rgb(var(--shade) / calc(.5 * var(--shadow-k)));
}

/* A hairline of colour under the header, brightest in the middle. It is the
   cheapest thing on the page and it does more than any other single rule. */
.site-header::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: -1px;
    height: 1px;
    pointer-events: none;
    background: linear-gradient(90deg,
        transparent, rgba(61, 220, 132, .45) 30%, rgba(67, 208, 255, .35) 62%, transparent);
    opacity: .7;
}

.nav {
    position: relative;
    max-width: var(--shell-max);
    margin: 0 auto;
    min-height: var(--nav-height);
    padding: 0 var(--space-5);
    display: flex;
    align-items: center;
    gap: var(--space-5);
}

.nav__brand {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    margin-right: auto;
    color: var(--text);
    text-decoration: none;
    font-weight: 700;
    font-size: 1.1rem;
    letter-spacing: -.03em;
    white-space: nowrap;
    /* It is a link home, and on a phone it was a 29px target. The nav bar has
       the room; nothing moves, the hit area just reaches the recommended
       minimum. */
    min-height: 44px;
}
.nav__brand:hover { color: var(--text); }

.nav__mark {
    display: block;
    filter: drop-shadow(0 0 12px rgba(61, 220, 132, .45));
    transition: transform var(--t-base) var(--ease-spring);
}
.nav__brand:hover .nav__mark { transform: rotate(-8deg) scale(1.06); }

.nav__wordmark { white-space: nowrap; }

.nav__list {
    list-style: none;
    display: flex;
    align-items: center;
    gap: 2px;
    margin: 0;
    padding: 0;
}

.nav__item { display: flex; }

.nav__link {
    position: relative;
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    padding: 0 13px;
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    text-decoration: none;
    font-size: .95rem;
    font-weight: 500;
    white-space: nowrap;
    transition: color var(--t-fast) var(--ease-out),
                background var(--t-fast) var(--ease-out);
}
.nav__link:hover {
    color: var(--text);
    background: rgb(var(--gloss) / .06);
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .07);
}

/* The underline grows from the middle rather than appearing, which is the
   difference between a hover state and a hover state that feels considered. */
.nav__link::after {
    content: '';
    position: absolute;
    left: 13px;
    right: 13px;
    bottom: 5px;
    height: 1.5px;
    border-radius: 2px;
    background: linear-gradient(90deg, var(--signal), var(--cyan));
    transform: scaleX(0);
    transition: transform var(--t-base) var(--ease-out);
}
.nav__link:hover::after { transform: scaleX(1); }

.nav__link[aria-current='page'] { color: var(--text); }
.nav__link[aria-current='page']::after { transform: scaleX(1); }

.nav__link--button {
    font: inherit;
    font-weight: 500;
    border: 0;
    background: none;
    cursor: pointer;
}

/* The one solid thing in the bar. Gradient face, bottom lip, glow on hover. */
.nav__link--cta {
    color: #07120c;
    font-weight: 700;
    background: linear-gradient(180deg, #56e79a, var(--signal) 55%, #2fc673);
    box-shadow:
        var(--lip),
        inset 0 1px 0 rgba(255, 255, 255, .45),
        0 2px 6px rgb(var(--shade) / calc(.35 * var(--shadow-k))),
        0 6px 20px -8px rgba(61, 220, 132, .6);
    padding: 0 16px;
}
.nav__link--cta:hover {
    color: #07120c;
    background: linear-gradient(180deg, #6bf0a9, #43e48c 55%, #34d07c);
    box-shadow:
        var(--lip-hover),
        inset 0 1px 0 rgba(255, 255, 255, .55),
        0 2px 6px rgb(var(--shade) / calc(.35 * var(--shadow-k))),
        0 10px 28px -8px rgba(61, 220, 132, .75);
}
.nav__link--cta::after { display: none; }

.nav__form { margin: 0; display: flex; }

/* -- The area badge ----------------------------------------------------------
   Which part of the application you are in, beside the wordmark. */

.nav__area {
    flex: none;
    padding: 4px 10px;
    border-radius: var(--radius-full);
    border: 1px solid var(--line-strong);
    background: linear-gradient(180deg, rgb(var(--gloss) / .06), rgb(var(--gloss) / .015));
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .07);
    color: var(--text-muted);
    font-family: var(--mono);
    font-size: .72rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    white-space: nowrap;
}

/* -- The account menu --------------------------------------------------------
   A <details>. It opens with no JavaScript and is keyboard operable for free.
   It does not close when you click elsewhere on the page, which is the one
   thing a few lines of script would buy and is not worth the dependency. */

.nav__item--account { margin-left: 6px; }

.nav__account { position: relative; }
.nav__account > summary { list-style: none; }
.nav__account > summary::-webkit-details-marker { display: none; }
.nav__account > summary::marker { content: ''; }

.nav__chip {
    display: flex;
    align-items: center;
    gap: 9px;
    min-height: 40px;
    padding: 0 12px 0 6px;
    border-radius: var(--radius-full);
    border: 1px solid var(--line-strong);
    background: linear-gradient(180deg, var(--surface-2), var(--surface-1));
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .08), var(--lip), 0 1px 2px rgb(var(--shade) / calc(.4 * var(--shadow-k)));
    color: var(--text);
    font-size: .9rem;
    font-weight: 500;
    cursor: pointer;
    user-select: none;
}
.nav__chip:hover { border-color: rgba(61, 220, 132, .4); }
.nav__chip:focus-visible { outline: 2px solid var(--signal-ink); outline-offset: 2px; }
.nav__chip-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 14ch; }

.nav__monogram {
    flex: none;
    display: grid;
    place-items: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: linear-gradient(145deg, #4fe396, #1f9c5c);
    color: #07120c;
    font-size: .78rem;
    font-weight: 700;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .45), 0 2px 8px -3px rgba(61, 220, 132, .85);
}

.nav__caret {
    flex: none;
    width: 7px;
    height: 7px;
    border-right: 1.6px solid currentColor;
    border-bottom: 1.6px solid currentColor;
    transform: rotate(45deg) translate(-1px, -1px);
    opacity: .55;
    transition: transform var(--t-fast) var(--ease-out);
}
.nav__account[open] .nav__caret { transform: rotate(-135deg) translate(-1px, -1px); }

.nav__menu {
    position: absolute;
    right: 0;
    top: calc(100% + 10px);
    z-index: 5;
    width: 260px;
    padding: var(--space-3);
    border-radius: var(--radius-lg);
    border: 1px solid var(--line-strong);
    background: linear-gradient(180deg, var(--surface-3), var(--surface-1));
    box-shadow:
        inset 0 1px 0 rgb(var(--gloss) / .09),
        0 4px 8px rgb(var(--shade) / calc(.5 * var(--shadow-k))),
        0 28px 56px -20px rgb(var(--shade) / calc(.95 * var(--shadow-k)));
}

.nav__menu-head {
    display: grid;
    gap: 2px;
    margin: 0 0 10px;
    padding: 0 8px 10px;
    border-bottom: 1px solid var(--line);
}
.nav__menu-name { font-size: .94rem; font-weight: 600; color: var(--text); }
.nav__menu-mail { font-family: var(--mono); font-size: .76rem; color: var(--text-dim); overflow-wrap: anywhere; }

.nav__menu-list { list-style: none; margin: 0 0 4px; padding: 0; display: grid; gap: 2px; }

.nav__menu-link {
    display: flex;
    align-items: center;
    width: 100%;
    min-height: 38px;
    padding: 0 10px;
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--text-muted);
    font: inherit;
    font-size: .92rem;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    transition: color var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out);
}
.nav__menu-link:hover { background: rgb(var(--gloss) / .06); color: var(--text); }
.nav__menu-link--signout { color: var(--danger); }
.nav__menu-link--signout:hover { background: rgba(255, 107, 107, .1); color: var(--danger); }


/* -- The mobile menu ---------------------------------------------------------
   A checkbox and a label. No JavaScript, so the menu works with scripting off,
   which is the rule here. The checkbox is hidden from sight but stays in the
   tab order, and the label carries the button role. */

/* Off screen, not display:none. display:none takes the checkbox out of the tab
   order and the menu becomes unreachable from a keyboard.

   Above the burger breakpoint it has to go the other way. The indicator is
   painted on .nav__burger, which is display:none there, so a focusable
   checkbox with no visible control is a tab stop where focus simply vanishes:
   you tab off the logo and the page goes dead. Remove the input wherever the
   thing it drives is not rendered. */
.nav__toggle {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
    margin: 0;
}

@media (min-width: 861px) {
    .nav__toggle { display: none; }
}

.nav__burger {
    display: none;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--line-strong);
    background: var(--surface-1);
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .06), var(--lip);
    cursor: pointer;
    flex: none;
}
.nav__burger:hover { background: var(--surface-2); }

.nav__burger-bars,
.nav__burger-bars::before,
.nav__burger-bars::after {
    display: block;
    width: 18px;
    height: 2px;
    border-radius: 2px;
    background: var(--text);
    transition: transform var(--t-base) var(--ease-out),
                opacity var(--t-fast) var(--ease-out);
}
.nav__burger-bars { position: relative; }
.nav__burger-bars::before { content: ''; position: absolute; top: -6px; }
.nav__burger-bars::after  { content: ''; position: absolute; top:  6px; }

.nav__toggle:checked ~ .nav__burger .nav__burger-bars { background: transparent; }
.nav__toggle:checked ~ .nav__burger .nav__burger-bars::before { transform: translateY(6px) rotate(45deg); }
.nav__toggle:checked ~ .nav__burger .nav__burger-bars::after  { transform: translateY(-6px) rotate(-45deg); }

.nav__toggle:focus-visible ~ .nav__burger { outline: 2px solid var(--signal-ink); outline-offset: 3px; }

/* -----------------------------------------------------------------------------
   Sidebar: the signed-in shell
   -------------------------------------------------------------------------- */

.layout__body {
    flex: 1 0 auto;
    display: grid;
    grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
    align-items: start;
    max-width: calc(var(--shell-max) + var(--sidebar-width) + var(--space-6));
    width: 100%;
    margin: 0 auto;
    gap: var(--space-6);
    padding: var(--space-6) var(--space-5) 0;
}

.layout--app .layout__main {
    max-width: 100%;
    margin: 0;
    padding: 0 0 var(--space-9);
    min-width: 0;
}

/* A dashboard heading is a label, not a headline. The marketing scale is too
   loud once there is a sidebar and a title bar above it. */
.layout--app .page { padding-top: 0; }
.layout--app .page__title { font-size: var(--text-2xl); }
.layout--app .page__lead { font-size: 1rem; }

/* A lit panel standing slightly proud of the page: a green wash at the top
   where the header light comes from, a hairline along the top edge, and a
   shadow cast onto the content. No ruled line anywhere on it. */
.sidebar {
    position: sticky;
    top: calc(var(--nav-height) + var(--space-5));
    align-self: start;
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    padding: var(--space-4);
    border-radius: var(--radius-lg);
    border: 1px solid var(--line);
    background:
        radial-gradient(340px 200px at 22% 0%, rgba(61, 220, 132, .09), transparent 70%),
        linear-gradient(180deg, var(--surface-2) 0%, var(--surface-1) 45%, var(--surface-sink) 100%);
    box-shadow:
        inset 0 1px 0 rgb(var(--gloss) / .08),
        0 2px 4px rgb(var(--shade) / calc(.4 * var(--shadow-k))),
        0 22px 48px -22px rgb(var(--shade) / calc(.85 * var(--shadow-k)));
    max-height: calc(100vh - var(--nav-height) - var(--space-7));
}

/* Only the list scrolls. The identity block stays pinned to the bottom. The
   negative margin puts the scrolling box flush against the panel's own edges
   and gives the padding back on the inside, because overflow-y also clips the
   x axis and the active rail sits outside the link. */
.sidebar__nav {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    display: grid;
    align-content: start;
    gap: var(--space-5);
    margin: 0 calc(var(--space-4) * -1);
    padding: 0 var(--space-4);
}

.sidebar__section { display: grid; gap: 6px; }

.sidebar__heading {
    margin: 0;
    padding: 0 12px;
    font-family: var(--mono);
    font-size: .72rem;
    font-weight: 500;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--text-dim);
}

.sidebar__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }

.sidebar__link {
    position: relative;
    display: flex;
    align-items: center;
    gap: 11px;
    min-height: 44px;
    padding: 6px 12px;
    border-radius: 11px;
    color: var(--text-muted);
    text-decoration: none;
    font-size: .93rem;
    font-weight: 500;
    transition: color var(--t-fast) var(--ease-out),
                background var(--t-fast) var(--ease-out),
                box-shadow var(--t-fast) var(--ease-out);
}

/* The glyph sits in a raised tile rather than floating on the background. The
   tile carries the state, which is what keeps the rail readable once the
   labels go at narrow widths. */
.sidebar__icon {
    flex: none;
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border-radius: 9px;
    border: 1px solid var(--line);
    background: linear-gradient(180deg, rgb(var(--gloss) / .06), rgb(var(--gloss) / .015));
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .07), 0 1px 2px rgb(var(--shade) / calc(.45 * var(--shadow-k)));
    color: var(--text-muted);
    transition: color var(--t-fast) var(--ease-out),
                border-color var(--t-fast) var(--ease-out),
                background var(--t-fast) var(--ease-out),
                box-shadow var(--t-fast) var(--ease-out);
}
.sidebar__glyph { display: block; }

.sidebar__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.sidebar__link:hover {
    color: var(--text);
    background: linear-gradient(180deg, rgb(var(--gloss) / .06), rgb(var(--gloss) / .02));
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .06);
}
.sidebar__link:hover .sidebar__icon { color: var(--text); border-color: var(--line-strong); }

.sidebar__link--active,
.sidebar__link[aria-current='page'] {
    color: var(--text);
    font-weight: 600;
    background: linear-gradient(90deg, rgba(61, 220, 132, .16), rgba(61, 220, 132, .03) 70%, transparent);
    box-shadow:
        inset 0 1px 0 rgb(var(--gloss) / .07),
        inset 0 0 0 1px rgba(61, 220, 132, .22),
        0 10px 24px -18px rgba(61, 220, 132, .9);
}

/* The indicator is a lit rail just inside the panel's left edge. The offset is
   the sidebar's own padding less a few pixels, so the rail clears the rounded
   corner instead of being sliced by it. */
.sidebar__link--active::before,
.sidebar__link[aria-current='page']::before {
    content: '';
    position: absolute;
    left: calc(var(--space-4) * -1 + 5px);
    top: 50%;
    transform: translateY(-50%);
    width: 3px;
    height: 22px;
    border-radius: 3px;
    background: linear-gradient(180deg, var(--signal), var(--cyan));
    box-shadow: 0 0 12px rgba(61, 220, 132, .85);
}

.sidebar__link--active .sidebar__icon,
.sidebar__link[aria-current='page'] .sidebar__icon {
    color: var(--signal-ink);
    border-color: rgba(61, 220, 132, .36);
    background: linear-gradient(180deg, rgba(61, 220, 132, .2), rgba(61, 220, 132, .06));
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .14), 0 0 14px -4px rgba(61, 220, 132, .75);
}

.sidebar__link:focus-visible,
.sidebar__switch:focus-visible { outline: 2px solid var(--signal-ink); outline-offset: 2px; border-radius: 11px; }

.sidebar__foot {
    flex: none;
    display: grid;
    gap: 10px;
    padding-top: var(--space-4);
    border-top: 1px solid var(--line);
}

.sidebar__switch {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    min-height: 42px;
    padding: 0 12px;
    border-radius: 11px;
    border: 1px solid var(--line-strong);
    background: linear-gradient(180deg, var(--surface-2), var(--surface-1));
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .07), var(--lip), 0 2px 6px -3px rgb(var(--shade) / calc(.7 * var(--shadow-k)));
    color: var(--text-muted);
    font-size: .88rem;
    font-weight: 500;
    text-decoration: none;
    transition: color var(--t-fast) var(--ease-out),
                border-color var(--t-fast) var(--ease-out),
                box-shadow var(--t-fast) var(--ease-out);
}
.sidebar__switch:hover {
    color: var(--text);
    border-color: rgba(61, 220, 132, .4);
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .1), var(--lip-hover), 0 10px 24px -14px rgba(61, 220, 132, .8);
}
.sidebar__switch-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.sidebar__switch-arrow {
    flex: none;
    width: 7px;
    height: 7px;
    border-top: 1.6px solid currentColor;
    border-right: 1.6px solid currentColor;
    transform: rotate(45deg);
    transition: transform var(--t-fast) var(--ease-out);
}
.sidebar__switch:hover .sidebar__switch-arrow { transform: rotate(45deg) translate(2px, -2px); }

.sidebar__who { display: flex; align-items: center; gap: 10px; min-width: 0; padding: 2px 4px; }

.sidebar__monogram {
    flex: none;
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    border-radius: 10px;
    background: linear-gradient(145deg, #4fe396, #1d8f55);
    color: #07120c;
    font-size: .85rem;
    font-weight: 700;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .45), 0 4px 12px -6px rgba(61, 220, 132, .9);
}

.sidebar__who-text { display: grid; min-width: 0; line-height: 1.3; }
.sidebar__who-name {
    font-size: .9rem;
    font-weight: 600;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.sidebar__who-role {
    font-family: var(--mono);
    font-size: .72rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--text-dim);
}

/* The marketing footer is wrong under a dashboard, and the app layout asks the
   partial for its compact shape rather than hiding the links with CSS. The
   difference is not cosmetic: `display: none` still ships every link in the
   markup, where a screen reader and a crawler both still find them. */
.layout--app .site-footer { margin-top: var(--space-7); background: transparent; }
.layout--app .site-footer__legal { border-top: 0; }

/* -----------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */

.site-footer {
    flex: none;
    position: relative;
    margin-top: var(--space-9);
    border-top: 1px solid var(--line);
    background:
        linear-gradient(180deg, rgb(var(--gloss) / .02), transparent 30%),
        var(--surface-sunken);
}

.site-footer::before {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: -1px;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(61, 220, 132, .35) 50%, transparent);
}

.site-footer__inner {
    max-width: var(--shell-max);
    margin: 0 auto;
    padding: var(--space-8) var(--space-5) var(--space-6);
    display: grid;
    grid-template-columns: minmax(220px, 1fr) 2.2fr;
    gap: var(--space-7);
}

.site-footer__mark {
    display: block;
    margin-bottom: var(--space-3);
    filter: drop-shadow(0 0 14px rgba(61, 220, 132, .35));
}
.site-footer__tagline { color: var(--text-muted); margin: 0; font-size: .94rem; line-height: 1.55; }

.site-footer__nav {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: var(--space-6);
}

.site-footer__heading {
    font-size: .7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .14em;
    color: var(--text-dim);
    margin: 0 0 var(--space-3);
}

.site-footer__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.site-footer__list a {
    color: var(--text-muted);
    text-decoration: none;
    font-size: .93rem;
    transition: color var(--t-fast) var(--ease-out);
}
.site-footer__list a:hover { color: var(--signal-ink); }

.site-footer__legal {
    max-width: var(--shell-max);
    margin: 0 auto;
    padding: var(--space-5) var(--space-5) var(--space-7);
    border-top: 1px solid var(--line);
}

.site-footer__legal {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-5);
}
.site-footer__identity { min-width: 0; }

.site-footer__text { margin: 0 0 4px; font-size: .86rem; color: var(--text-muted); }
.site-footer__text--muted { color: var(--text-dim); font-size: .8rem; }

/* -- The light/dark switch ---------------------------------------------------
   Three submit buttons in a segmented control. No scripting, because there is
   none anywhere on this site: each button posts, the server writes a cookie
   and stamps the attribute, and the page comes back already in the new theme
   with no flash of the old one. */

.appearance {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
    margin: 0;
}

.appearance__label {
    font-family: var(--mono);
    font-size: .72rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--text-dim);
}

.appearance__set {
    display: flex;
    padding: 4px;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-full);
    background: var(--surface-sunken);
}

.appearance__btn {
    display: inline-flex;
    align-items: center;
    min-height: 38px;
    padding: 0 14px;
    border: 0;
    border-radius: var(--radius-full);
    background: transparent;
    color: var(--text-muted);
    font: inherit;
    font-size: .84rem;
    font-weight: 600;
    cursor: pointer;
    transition: background var(--t-fast) var(--ease-out),
                color var(--t-fast) var(--ease-out);
}
.appearance__btn:hover { background: rgb(var(--gloss) / .06); color: var(--text); }
.appearance__btn:focus-visible { outline: 2px solid var(--signal-ink); outline-offset: 2px; }

/* The one in force. Disabled, because pressing it is a page load that changes
   nothing, so it must not look or behave like something waiting to be pressed:
   the cursor is the default one and the hover does not fire. */
.appearance__btn--on {
    background: var(--surface-2);
    border: 1px solid var(--line);
    color: var(--text);
    cursor: default;
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .08);
}
.appearance__btn--on:hover { background: var(--surface-2); color: var(--text); }
.appearance__btn[disabled] { opacity: 1; }

@media (max-width: 560px) {
    .site-footer__legal { justify-content: flex-start; }
    .appearance { width: 100%; }
    .appearance__set { flex: 1 1 auto; }
    .appearance__btn { flex: 1 1 0; justify-content: center; padding: 0 8px; }
}

/* -----------------------------------------------------------------------------
   Hero
   -------------------------------------------------------------------------- */

.hero {
    position: relative;
    display: grid;
    grid-template-columns: 1.04fr .96fr;
    gap: var(--space-8);
    align-items: center;
    padding: var(--space-8) 0 var(--space-7);
}
.hero > * { min-width: 0; position: relative; z-index: 1; }

.hero__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    font-family: var(--mono);
    font-size: .76rem;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--signal-ink);
    padding: 6px 13px;
    border-radius: var(--radius-full);
    border: 1px solid transparent;
    /* Opaque. The two-layer gradient-border technique only works when the
       padding-box layer is solid: at 8% alpha 92% of the border gradient
       shows through the face, the pill renders bright teal, and the Signal
       Green label on it measures 3.27:1. */
    background:
        linear-gradient(var(--surface-pill) 0 0) padding-box,
        linear-gradient(135deg, rgba(61, 220, 132, .55), rgba(67, 208, 255, .3), rgba(61, 220, 132, .1)) border-box;
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .08), 0 4px 16px -6px rgba(61, 220, 132, .5);
    margin-bottom: var(--space-5);
}

.hero__title {
    /* A notch below --text-5xl. This headline is two clauses, and at the full
       display size the second one orphans its last word on every width from
       1100 to 1440. */
    font-size: clamp(2.3rem, 4.6vw, 3.5rem);
    font-weight: 700;
    line-height: 1.03;
    letter-spacing: -.04em;
    margin-bottom: .4em;
    text-wrap: balance;
}
.hero__title em { font-style: normal; color: var(--signal-ink); }

.hero__lead {
    font-size: 1.14rem;
    color: var(--text-muted);
    max-width: 52ch;
    margin: 0 0 var(--space-6);
}

.hero__actions { display: flex; gap: var(--space-3); flex-wrap: wrap; align-items: center; }

.hero__note { color: var(--text-dim); font-size: .89rem; margin: var(--space-5) 0 0; }

/* Backwards-compatible alias: .hero__pulse is emitted by the home view. */
.hero__pulse {
    position: relative;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--signal);
    flex: none;
    box-shadow: 0 0 8px rgba(61, 220, 132, .9);
}
.hero__pulse::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
    box-shadow: 0 0 0 0 rgba(61, 220, 132, .7);
    animation: pulse-ring 2.4s var(--ease-out) infinite;
}

/* -----------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */

.btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 44px;
    padding: 0 20px;
    border-radius: var(--radius-md);
    border: 1px solid var(--line-strong);
    background: linear-gradient(180deg, var(--surface-2), var(--surface-1));
    color: var(--text);
    font: inherit;
    font-size: .97rem;
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
    box-shadow:
        inset 0 1px 0 rgb(var(--gloss) / .08),
        var(--lip),
        0 1px 2px rgb(var(--shade) / calc(.4 * var(--shadow-k))),
        0 6px 16px -8px rgb(var(--shade) / calc(.6 * var(--shadow-k)));
    transition: background var(--t-fast) var(--ease-out),
                border-color var(--t-fast) var(--ease-out),
                box-shadow var(--t-fast) var(--ease-out),
                transform var(--t-fast) var(--ease-out);
}
.btn:hover {
    color: var(--text);
    background: linear-gradient(180deg, var(--surface-3), var(--surface-2));
    border-color: rgb(var(--gloss) / .2);
    box-shadow:
        inset 0 1px 0 rgb(var(--gloss) / .12),
        var(--lip-hover),
        0 1px 2px rgb(var(--shade) / calc(.4 * var(--shadow-k))),
        0 10px 24px -8px rgb(var(--shade) / calc(.7 * var(--shadow-k)));
    transform: translateY(-1px);
}
.btn:active {
    transform: translateY(1px);
    box-shadow: inset 0 2px 6px rgb(var(--shade) / calc(.5 * var(--shadow-k))), var(--lip-active);
}

.btn--primary {
    border-color: rgba(61, 220, 132, .55);
    color: #07120c;
    background: linear-gradient(180deg, #5ceb9f, var(--signal) 52%, #2ec570);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .5),
        var(--lip),
        0 2px 6px rgb(var(--shade) / calc(.35 * var(--shadow-k))),
        0 10px 30px -10px rgba(61, 220, 132, .7);
}
.btn--primary:hover {
    color: #07120c;
    background: linear-gradient(180deg, #74f4b1, #46e491 52%, #33d27c);
    border-color: rgba(61, 220, 132, .75);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .6),
        var(--lip-hover),
        0 2px 6px rgb(var(--shade) / calc(.35 * var(--shadow-k))),
        0 16px 42px -12px rgba(61, 220, 132, .85);
}

.btn--ghost {
    background: transparent;
    border-color: var(--line);
    box-shadow: none;
    color: var(--text-muted);
}
.btn--ghost:hover {
    background: rgb(var(--gloss) / .05);
    border-color: var(--line-strong);
    color: var(--text);
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .07);
}

.btn--link {
    min-height: 44px;
    border-color: transparent;
    background: none;
    box-shadow: none;
    color: var(--signal-ink);
    padding: 0 10px;
}
.btn--link:hover {
    background: rgba(61, 220, 132, .08);
    border-color: transparent;
    box-shadow: none;
    transform: none;
    color: #6fe9a8;
}

.btn--block { width: 100%; }
.btn--sm { min-height: 36px; padding: 0 14px; font-size: .88rem; }

/* The home view emits .btn--shimmer. effects.css owns the animation; this only
   provides the containment it needs. */
.btn--shimmer { position: relative; overflow: hidden; isolation: isolate; }
.btn--shimmer::after {
    content: '';
    position: absolute;
    top: 0;
    left: -80%;
    width: 45%;
    height: 100%;
    background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .5), transparent);
    animation: shimmer-slide 3.4s ease-in-out infinite;
    pointer-events: none;
}

.actions { display: flex; gap: var(--space-3); flex-wrap: wrap; margin: var(--space-6) 0 0; align-items: center; }
.actions__form { margin: 0; display: flex; }

.links { list-style: none; margin: var(--space-5) 0 0; padding: 0; display: grid; gap: 10px; }
.links__item { font-size: .93rem; }

.badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: var(--mono);
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .1em;
    padding: 4px 10px;
    border-radius: var(--radius-full);
    background: rgba(61, 220, 132, .12);
    border: 1px solid rgba(61, 220, 132, .32);
    color: var(--signal-ink);
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .08);
}

/* -----------------------------------------------------------------------------
   Code sample
   -------------------------------------------------------------------------- */
/* Cut into the page, not laid on it. A terminal that sits above the surface
   never looks like a terminal. */

.code {
    position: relative;
    background: var(--surface-sunken);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow:
        inset 0 1px 0 rgb(var(--gloss) / .04),
        inset 0 4px 20px rgb(var(--shade) / calc(.6 * var(--shadow-k))),
        0 20px 50px -18px rgb(var(--shade) / calc(.85 * var(--shadow-k))),
        0 0 0 1px rgb(var(--gloss) / .02);
}

.code__bar {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 11px 15px;
    border-bottom: 1px solid var(--line);
    background: linear-gradient(180deg, rgb(var(--gloss) / .05), rgb(var(--gloss) / .015));
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .07);
    font-family: var(--mono);
    font-size: .74rem;
    letter-spacing: .04em;
    color: var(--text-dim);
}

.code__dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--chrome);
    box-shadow: inset 0 1px 1px rgb(var(--shade) / calc(.6 * var(--shadow-k))), 0 1px 0 rgb(var(--gloss) / .06);
    flex: none;
}
.code__dot:first-child { background: #3ddc84; box-shadow: 0 0 8px rgba(61, 220, 132, .7); }
.code__bar span:last-child { margin-left: auto; }

.code__body {
    margin: 0;
    padding: 18px;
    overflow-x: auto;
    font-size: .83rem;
    line-height: 1.75;
    color: var(--text);
    tab-size: 2;
}

.tok-key   { color: #9ecbff; }
.tok-str   { color: var(--signal-ink); }
.tok-num   { color: var(--amber-ink); }
.tok-bool  { color: var(--violet-ink); }
.tok-punct { color: var(--text-dim); }

/* -----------------------------------------------------------------------------
   Sections and grids
   -------------------------------------------------------------------------- */

.section { position: relative; padding: var(--space-9) 0; }

/* A divider that fades out at both ends instead of a full-width rule. */
.section::before {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--line-strong) 20%, var(--line-strong) 80%, transparent);
}
.section:first-of-type::before { display: none; }

/* The strip under the hero is a continuation of it, not a new chapter. */
.section--tight { padding: var(--space-6) 0 var(--space-8); }
.section--tight::before { display: none; }
.section--tight .stats { margin-top: var(--space-7); }

.section__head { max-width: var(--measure); margin-bottom: var(--space-7); }
.section__title { font-size: var(--text-3xl); font-weight: 700; text-wrap: balance; }
.section__lead { color: var(--text-muted); font-size: 1.05rem; margin: 0; }

.grid { display: grid; gap: var(--space-4); }
.grid > * { min-width: 0; }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.grid--plans { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); align-items: stretch; }

/* -----------------------------------------------------------------------------
   Cards
   -------------------------------------------------------------------------- */
/* The shared recipe: a hairline, a top highlight, an ambient inner glow rising
   from the bottom, and a shadow that deepens the ground rather than lifting
   the card. All four, every time. */

.card,
.feature,
.plan,
.legal-card {
    position: relative;
    border-radius: var(--radius-lg);
    border: 1px solid var(--line);
    background:
        linear-gradient(180deg, rgb(var(--gloss) / .04), transparent 35%),
        var(--surface-1);
    box-shadow:
        inset 0 1px 0 rgb(var(--gloss) / .07),
        inset 0 -30px 60px -30px rgb(var(--gloss) / .06),
        0 1px 2px rgb(var(--shade) / calc(.4 * var(--shadow-k))),
        0 14px 34px -14px rgb(var(--shade) / calc(.7 * var(--shadow-k)));
}

.card { padding: var(--space-5); }

.card--auth {
    width: 100%;
    max-width: 440px;
    padding: var(--space-6);
    border-radius: var(--radius-xl);
    box-shadow:
        inset 0 1px 0 rgb(var(--gloss) / .09),
        inset 0 -40px 80px -40px rgba(61, 220, 132, .12),
        0 2px 4px rgb(var(--shade) / calc(.5 * var(--shadow-k))),
        0 40px 80px -30px rgb(var(--shade) / calc(.9 * var(--shadow-k)));
}

.card__brand {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    margin-bottom: var(--space-5);
    color: var(--text);
    text-decoration: none;
    font-weight: 700;
    font-size: 1.12rem;
    letter-spacing: -.03em;
}
.card__brand:hover { color: var(--text); }
.card__brand img { flex: none; filter: drop-shadow(0 0 12px rgba(61, 220, 132, .45)); }

.card__title { font-size: 1.28rem; margin-bottom: var(--space-4); }

.feature { padding: var(--space-5); }
.feature__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    margin-bottom: var(--space-3);
    border-radius: var(--radius-sm);
    font-family: var(--mono);
    font-size: .68rem;
    font-weight: 500;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--signal-ink);
    background: rgba(61, 220, 132, .1);
    border: 1px solid rgba(61, 220, 132, .26);
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .1), 0 4px 14px -6px rgba(61, 220, 132, .5);
}
.feature__title { font-size: 1.06rem; margin-bottom: 8px; }
.feature__text { color: var(--text-muted); margin: 0; font-size: .95rem; }

/* .magic-card and .shine are emitted by the home view. */
.magic-card {
    transition: transform var(--t-base) var(--ease-out),
                border-color var(--t-base) var(--ease-out),
                box-shadow var(--t-base) var(--ease-out);
}
.magic-card:hover {
    transform: translateY(-4px);
    border-color: var(--line-strong);
    box-shadow:
        inset 0 1px 0 rgb(var(--gloss) / .1),
        inset 0 -30px 60px -30px rgba(61, 220, 132, .16),
        0 2px 4px rgb(var(--shade) / calc(.5 * var(--shadow-k))),
        0 28px 60px -20px rgb(var(--shade) / calc(.85 * var(--shadow-k)));
}

.shine { position: relative; overflow: hidden; }
.shine::after {
    content: '';
    position: absolute;
    top: 0;
    left: -60%;
    width: 42%;
    height: 100%;
    background: linear-gradient(100deg, transparent, rgb(var(--gloss) / .06), transparent);
    animation: sheen-sweep 8s ease-in-out infinite;
    pointer-events: none;
}

/* .border-beam is the older hook the home view still uses. Same ring cut-out
   as .beam in effects.css. */
.border-beam {
    position: absolute;
    inset: 0;
    border-radius: inherit;
    padding: 1px;
    pointer-events: none;
    overflow: hidden;
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
            mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
            mask-composite: exclude;
}
.border-beam::before {
    content: '';
    position: absolute;
    inset: -60%;
    background: conic-gradient(from 0turn,
        transparent 0turn, transparent .58turn,
        var(--signal) .76turn, var(--cyan) .86turn, var(--violet) .93turn,
        transparent 1turn);
    animation: beam-spin 6s linear infinite;
}

/* -----------------------------------------------------------------------------
   Aurora text
   -------------------------------------------------------------------------- */
/* Lives here rather than in effects.css because it is the only class in that
   file any markup uses, and 15 KB of render-blocking CSS to deliver one rule
   is not a trade worth making. effects.css stays on disk as a pattern library
   and is no longer loaded.

   `display: inline`, not inline-block: an inline-block is an atomic box the
   line breaker cannot split, which is why text-wrap: balance was leaving 26%
   of the headline's first line empty.

   The keyframes animate background-position only. The original also rotated
   and scaled, and neither can be composited on text-clipped gradient fill, so
   every frame repainted the H1 glyph by glyph: 227ms of paint and raster per
   three seconds on an idle page, about half the homepage's total. */
.aurora {
    display: inline;
    -webkit-box-decoration-break: clone;
            box-decoration-break: clone;
    /* Green through cyan and back. The four-hue version ran green, cyan,
       violet, pink in one headline, which put seven colours above the fold
       once the gauge and the syntax highlighting were counted, and stopped
       the gradient reading as deliberate. */
    background-image: linear-gradient(135deg,
        var(--signal), var(--cyan) 45%, #7fe7c4 70%, var(--signal));
    background-size: 200% auto;
    -webkit-background-clip: text;
            background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    animation: aurora 10s ease-in-out infinite alternate;
}

@keyframes aurora {
    0%   { background-position:   0% 50%; }
    25%  { background-position:  50% 100%; }
    50%  { background-position: 100% 50%; }
    75%  { background-position:  50% 0%; }
    100% { background-position:   0% 50%; }
}

/* .fade-in is the older name for .rise. No fill-mode, and the stagger is a
   longer duration rather than a delay: effects.css explains why at .rise. */
.fade-in { animation: rise var(--t-slow) var(--ease-out); }
.fade-in--delay { animation-duration: 640ms; }

/* -----------------------------------------------------------------------------
   Pricing
   -------------------------------------------------------------------------- */

.plan {
    padding: var(--space-6) var(--space-5);
    display: flex;
    flex-direction: column;
    transition: transform var(--t-base) var(--ease-out),
                border-color var(--t-base) var(--ease-out),
                box-shadow var(--t-base) var(--ease-out);
}
.plan:hover {
    transform: translateY(-3px);
    border-color: var(--line-strong);
    box-shadow:
        inset 0 1px 0 rgb(var(--gloss) / .1),
        inset 0 -30px 60px -30px rgb(var(--gloss) / .09),
        0 24px 54px -18px rgb(var(--shade) / calc(.85 * var(--shadow-k)));
}

/* The featured plan sits one step further forward: brighter face, a coloured
   inner glow and a real glow outside. */
.plan--featured {
    border-color: transparent;
    background:
        linear-gradient(180deg, var(--surface-2), var(--surface-1)) padding-box,
        linear-gradient(160deg, var(--signal), rgba(67, 208, 255, .55) 50%, rgba(169, 124, 248, .4)) border-box;
    box-shadow:
        inset 0 1px 0 rgb(var(--gloss) / .11),
        inset 0 -50px 90px -50px rgba(61, 220, 132, .3),
        0 2px 4px rgb(var(--shade) / calc(.5 * var(--shadow-k))),
        0 26px 60px -20px rgba(61, 220, 132, .35);
    transform: translateY(-6px);
}
.plan--featured:hover { transform: translateY(-10px); }

.plan__badge {
    position: absolute;
    top: -12px;
    left: var(--space-5);
    background: linear-gradient(180deg, #5ceb9f, var(--signal));
    color: #07120c;
    font-size: .66rem;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    padding: 4px 11px;
    border-radius: var(--radius-full);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), 0 6px 18px -6px rgba(61, 220, 132, .8);
}

.plan__name {
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--text-dim);
    margin-bottom: var(--space-3);
}

.plan__price {
    display: block;
    font-size: 2.3rem;
    font-weight: 700;
    letter-spacing: -.04em;
    line-height: 1;
    color: var(--text);
}
.plan__period { font-size: .88rem; color: var(--text-dim); font-weight: 400; letter-spacing: 0; }
.plan__note { color: var(--text-dim); font-size: .82rem; margin: var(--space-3) 0 0; }

.plan__list {
    list-style: none;
    margin: var(--space-5) 0 var(--space-5);
    padding: var(--space-4) 0 0;
    border-top: 1px solid var(--line);
    display: grid;
    gap: 10px;
    font-size: .92rem;
}
.plan__list li { color: var(--text-muted); padding-left: 24px; position: relative; }
.plan__list li::before {
    content: '';
    position: absolute;
    left: 0;
    top: .45em;
    width: 15px;
    height: 15px;
    border-radius: 50%;
    background: rgba(61, 220, 132, .14);
    border: 1px solid rgba(61, 220, 132, .4);
}
.plan__list li::after {
    content: '';
    position: absolute;
    left: 5px;
    top: .72em;
    width: 4px;
    height: 7px;
    border: solid var(--signal);
    border-width: 0 1.5px 1.5px 0;
    transform: rotate(45deg);
}
.plan__list li strong { color: var(--text); font-weight: 600; }

.plan__cta { margin-top: auto; }
.plan__cta .btn { width: 100%; }

/* -----------------------------------------------------------------------------
   Score and flags
   -------------------------------------------------------------------------- */

.score { display: flex; align-items: center; gap: var(--space-4); margin: 4px 0 var(--space-4); }

.score__value {
    font-family: var(--mono);
    font-size: 2.5rem;
    font-weight: 500;
    line-height: 1;
    letter-spacing: -.03em;
    text-shadow: 0 0 24px rgba(255, 107, 107, .35);
}

.score__band {
    font-family: var(--mono);
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .12em;
    padding: 5px 11px;
    border-radius: var(--radius-full);
    background: rgba(255, 107, 107, .13);
    border: 1px solid rgba(255, 107, 107, .35);
    color: var(--danger);
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .08), 0 0 20px -6px rgba(255, 107, 107, .6);
}

/* display:block matters on both. They are spans, and width is ignored on an
   inline element, so the meter renders as an empty groove without it. */
.score__meter {
    display: block;
    flex: 1;
    height: 9px;
    border-radius: var(--radius-full);
    background: var(--surface-sunken);
    /* The track needs a visible extent or the bar shows a proportion of
       nothing: the fill reads fine and the empty part measured 1.08:1. */
    border: 1px solid var(--track-edge);
    box-shadow: inset 0 2px 5px rgb(var(--shade) / calc(.8 * var(--shadow-k))), inset 0 -1px 0 rgb(var(--gloss) / .05);
    overflow: hidden;
    min-width: 80px;
}
.score__fill {
    display: block;
    height: 100%;
    border-radius: var(--radius-full);
    background: linear-gradient(90deg, var(--signal), var(--warn) 55%, var(--danger));
    box-shadow: 0 0 14px rgba(255, 107, 107, .55), inset 0 1px 0 rgba(255, 255, 255, .3);
    animation: score-grow 1.1s var(--ease-out);
    transform-origin: left;
}

/* Width steps for the score meter, in tens.

   These exist because the Content-Security-Policy forbids inline styles, and
   unlike scripts a style ATTRIBUTE cannot be allowed by a hash or a nonce:
   it is 'unsafe-inline' or nothing. A handful of classes is a better trade
   than weakening the policy for the whole site.

   When the dashboard renders a real score, round to the nearest step here, or
   emit a nonced <style> element, which CSP does allow. Do not reach for
   'unsafe-inline'. */
.score__fill--10  { width:  10%; }
.score__fill--20  { width:  20%; }
.score__fill--30  { width:  30%; }
.score__fill--40  { width:  40%; }
.score__fill--50  { width:  50%; }
.score__fill--60  { width:  60%; }
.score__fill--70  { width:  70%; }
.score__fill--80  { width:  80%; }
.score__fill--90  { width:  90%; }
.score__fill--100 { width: 100%; }

@keyframes score-grow {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
}

.flagrow { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
.flag {
    font-family: var(--mono);
    font-size: .76rem;
    padding: 5px 11px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--line);
    color: var(--text-dim);
    background: var(--surface-sunken);
    box-shadow: inset 0 1px 3px rgb(var(--shade) / calc(.5 * var(--shadow-k)));
}
.flag--on {
    color: var(--signal-ink);
    border-color: rgba(61, 220, 132, .38);
    background: rgba(61, 220, 132, .1);
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .1), 0 0 18px -6px rgba(61, 220, 132, .7);
}
/* An explicit colour, not an opacity: opacity drags the border under 3:1 with
   the text. The strikethrough stays as the second, non-colour cue. */
.flag--off { text-decoration: line-through; color: var(--text-dim); border-color: var(--line); }

/* -----------------------------------------------------------------------------
   Pages and long-form text
   -------------------------------------------------------------------------- */

.page { padding-top: var(--space-7); }
.page__header { margin-bottom: var(--space-6); }
.page__title { font-size: var(--text-4xl); font-weight: 700; text-wrap: balance; }
.page__lead { color: var(--text-muted); font-size: 1.07rem; max-width: var(--measure); margin: 0; }
.page__text { color: var(--text-muted); max-width: var(--measure); }

.page--auth { padding-top: 0; }
.page--auth .page__header { margin-bottom: var(--space-5); }
.page--auth .page__title { font-size: var(--text-2xl); }

.page--error { text-align: center; padding: var(--space-9) 0; }
.page--error .page__title {
    font-family: var(--mono);
    font-size: clamp(3.5rem, 12vw, 6rem);
    font-weight: 400;
    /* Stops at --text-dim rather than running to transparent: the bottom third
       of every glyph was measuring 2.56:1. */
    background: linear-gradient(180deg, var(--text-muted), var(--text-dim));
    -webkit-background-clip: text;
            background-clip: text;
    -webkit-text-fill-color: transparent;
}
.page--error .actions { justify-content: center; }
.page--error .page__text { margin-inline: auto; text-align: center; }

.onward { margin: var(--space-7) auto 0; max-width: 620px; }

.onward__label {
    margin: 0 0 var(--space-4);
    font-family: var(--mono);
    font-size: .68rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--text-dim);
}

.onward__list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: 10px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.onward__link {
    display: flex;
    align-items: center;
    min-height: 48px;
    padding: 0 var(--space-4);
    border-radius: var(--radius-md);
    border: 1px solid var(--line);
    background: var(--surface-1);
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .05);
    color: var(--text-muted);
    text-decoration: none;
    font-size: .93rem;
    text-align: left;
    transition: color var(--t-fast) var(--ease-out),
                border-color var(--t-fast) var(--ease-out),
                background var(--t-fast) var(--ease-out);
}
.onward__link:hover {
    color: var(--text);
    border-color: var(--line-strong);
    background: var(--surface-2);
}

/* Breadcrumbs. Two levels deep is already enough to need a way back, and the
   trail is the only thing on a legal page that says where you are. */
.crumbs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: var(--space-4);
    font-size: .84rem;
    color: var(--text-dim);
}

.crumbs a {
    color: var(--text-muted);
    text-decoration: none;
    padding: 4px 0;
}
.crumbs a:hover { color: var(--signal-ink); }

.crumbs > * + *::before {
    content: '/';
    margin-right: 8px;
    color: var(--text-dim);
    opacity: .6;
}

.crumbs [aria-current] { color: var(--text-dim); }

/* A legal document is a document. Left-aligning a 45rem column inside an
   1180px shell leaves 500px of nothing beside it and makes the page read as
   broken rather than as considered. */
.page--legal {
    max-width: var(--measure);
    margin-inline: auto;
}

/* Long documents earn a little more air between their sections. */
.page--legal .prose h2 { margin-top: var(--space-8); }

.prose { max-width: var(--measure); }
.prose h2 {
    font-size: 1.34rem;
    font-weight: 700;
    margin: var(--space-7) 0 .5em;
    padding-top: var(--space-5);
    border-top: 1px solid var(--line);
}
.prose h2:first-of-type { border-top: 0; padding-top: 0; margin-top: var(--space-6); }
.prose h3 { font-size: 1.06rem; margin: var(--space-6) 0 .4em; color: var(--text); }
.prose p, .prose li { color: var(--text-muted); }
.prose ul, .prose ol { padding-left: 22px; display: grid; gap: 8px; }
.prose strong { color: var(--text); font-weight: 600; }
.prose address { font-style: normal; color: var(--text-muted); }
.prose a { font-weight: 500; }

.prose__meta {
    font-family: var(--mono);
    font-size: .79rem;
    color: var(--text-dim);
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    padding: 13px 16px;
    background: var(--surface-sunken);
    box-shadow: inset 0 1px 4px rgb(var(--shade) / calc(.5 * var(--shadow-k)));
    margin-bottom: var(--space-2);
}

.callout {
    position: relative;
    border: 1px solid var(--line);
    background:
        linear-gradient(90deg, rgba(61, 220, 132, .07), transparent 40%),
        var(--surface-1);
    border-radius: var(--radius-md);
    padding: var(--space-4) var(--space-5);
    margin: var(--space-5) 0;
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .06);
    overflow: hidden;
}
.callout::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: linear-gradient(180deg, var(--signal), var(--cyan));
    box-shadow: 0 0 14px rgba(61, 220, 132, .7);
}
.callout p { margin: 0; color: var(--text-muted); font-size: .95rem; }
.callout p + p { margin-top: .6em; }
.callout--warn { background: linear-gradient(90deg, rgba(255, 200, 107, .07), transparent 40%), var(--surface-1); }
.callout--warn::before { background: linear-gradient(180deg, var(--warn), var(--amber)); box-shadow: 0 0 14px rgba(255, 200, 107, .6); }

.callout--danger { background: linear-gradient(90deg, rgba(255, 107, 107, .08), transparent 40%), var(--surface-1); }
.callout--danger::before { background: linear-gradient(180deg, var(--danger), var(--warn)); box-shadow: 0 0 14px rgba(255, 107, 107, .6); }

.legal-index { display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); gap: var(--space-4); }

.legal-card {
    display: block;
    padding: var(--space-5);
    text-decoration: none;
    overflow: hidden;
    transition: transform var(--t-base) var(--ease-out),
                border-color var(--t-base) var(--ease-out),
                box-shadow var(--t-base) var(--ease-out);
}
.legal-card::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0;
    background: radial-gradient(360px circle at 50% -20%, rgba(61, 220, 132, .14), transparent 70%);
    transition: opacity var(--t-base) var(--ease-out);
}
.legal-card:hover {
    transform: translateY(-3px);
    border-color: var(--line-strong);
    box-shadow:
        inset 0 1px 0 rgb(var(--gloss) / .1),
        0 24px 50px -18px rgb(var(--shade) / calc(.85 * var(--shadow-k)));
}
.legal-card:hover::after { opacity: 1; }
.legal-card__title { color: var(--text); font-size: 1.04rem; font-weight: 600; margin: 0 0 6px; }
.legal-card__text { color: var(--text-muted); font-size: .92rem; margin: 0; }

/* -----------------------------------------------------------------------------
   Forms
   -------------------------------------------------------------------------- */

.form { display: grid; gap: var(--space-4); }
.field { display: grid; gap: 7px; }
.field__label { font-size: .87rem; font-weight: 600; color: var(--text); letter-spacing: -.005em; }

/* Recessed. An input that sits above the page is the single clearest sign of
   a design that has never thought about depth. */
.field__input {
    width: 100%;
    min-height: 44px;
    padding: 11px 14px;
    font: inherit;
    font-size: .97rem;
    color: var(--text);
    background: var(--surface-sunken);
    border: 1px solid var(--line-control);
    border-radius: var(--radius-md);
    box-shadow: inset 0 2px 5px rgb(var(--shade) / calc(.55 * var(--shadow-k))), inset 0 -1px 0 rgb(var(--gloss) / .04);
    transition: border-color var(--t-fast) var(--ease-out),
                box-shadow var(--t-fast) var(--ease-out),
                background var(--t-fast) var(--ease-out);
}
.field__input:hover { border-color: rgb(var(--gloss) / .46); }

/* The ring replaces the outline, so it must be at least as visible. Keyboard
   users get the same ring plus the browser's own on :focus-visible. */
/* One treatment, not four. This used to stack a green border, a 3px spread
   ring, a 24px glow AND an outline on the same element, which is a lot of
   shouting for a text box, and the autofocus on the auth forms meant it was
   the first thing the page did. */
.field__input:focus {
    outline: none;
    border-color: rgba(61, 220, 132, .7);
    background: var(--surface-focus);
    box-shadow: inset 0 2px 5px rgb(var(--shade) / calc(.55 * var(--shadow-k))), 0 0 0 3px rgba(61, 220, 132, .18);
}
.field__input:focus-visible { outline: 2px solid var(--signal-ink); outline-offset: 2px; }
.field__input::placeholder { color: var(--text-dim); }

textarea.field__input { min-height: 120px; resize: vertical; line-height: 1.6; }
select.field__input { appearance: none; padding-right: 36px; cursor: pointer; }

.field__hint { font-size: .82rem; color: var(--text-dim); }
.field__error { font-size: .85rem; color: var(--danger); }

.field--check { display: flex; align-items: flex-start; gap: 10px; }
.field--check .field__label { font-weight: 400; font-size: .9rem; color: var(--text-muted); line-height: 1.5; }
.field__check {
    position: relative;
    flex: none;
    width: 22px;
    height: 22px;
    margin: 2px 0 0;
    accent-color: var(--signal);
    cursor: pointer;
    border: 1px solid var(--line-control);
    border-radius: 4px;
}

/* The drawn box stays 22px; the target is 34. WCAG 2.2 sets the floor at 24
   and this one gates a contract, so it is worth more than the floor. */
.field__check::before {
    content: '';
    position: absolute;
    inset: -6px;
}

/* The captcha widget. Turnstile renders a 300x65 iframe into this element and
   sets its own inline width, so the container only has to give it room and not
   clip it. min-height reserves the space before the script has run, or the
   submit button jumps down the moment it does. */
.captcha {
    margin: 2px 0;
    min-height: 65px;
}
.captcha:empty { min-height: 0; }

/* Turnstile can widen past a narrow card on a small phone. Let it scroll
   rather than push the whole form sideways. */
@media (max-width: 380px) {
    .captcha { overflow-x: auto; }
}

.form__foot {
    margin: var(--space-5) 0 0;
    padding-top: var(--space-4);
    border-top: 1px solid var(--line);
    font-size: .88rem;
    color: var(--text-muted);
}

/* -----------------------------------------------------------------------------
   Alerts
   -------------------------------------------------------------------------- */

.alerts { display: grid; gap: 10px; margin: 0 0 var(--space-5); }

/* The region now renders on every page whether or not it has anything in it,
   because a live region only announces content inserted AFTER it is in the
   accessibility tree. An empty one must cost no space. */
.alerts:empty { display: none; margin: 0; }

/* Focusable so an error can be moved to. It must not draw a ring for a mouse
   user who happens to click near it. */
.layout__main:focus,
.alerts:focus { outline: none; }

.alert {
    position: relative;
    padding: 13px 16px 13px 18px;
    border-radius: var(--radius-md);
    border: 1px solid var(--line);
    background: var(--surface-1);
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .06), 0 8px 24px -12px rgb(var(--shade) / calc(.8 * var(--shadow-k)));
    font-size: .94rem;
    overflow: hidden;
}
.alert::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; }

.alert--success { border-color: rgba(61, 220, 132, .32);  background: linear-gradient(90deg, rgba(61, 220, 132, .1), transparent 45%), var(--surface-1);  color: var(--signal-ink); }
.alert--info    { border-color: rgba(107, 184, 255, .32); background: linear-gradient(90deg, rgba(107, 184, 255, .1), transparent 45%), var(--surface-1); color: var(--info); }
.alert--warning { border-color: rgba(255, 200, 107, .32); background: linear-gradient(90deg, rgba(255, 200, 107, .1), transparent 45%), var(--surface-1); color: var(--warn); }
.alert--danger  { border-color: rgba(255, 107, 107, .32); background: linear-gradient(90deg, rgba(255, 107, 107, .1), transparent 45%), var(--surface-1); color: var(--danger); }

.alert--success::before { background: var(--signal); box-shadow: 0 0 12px rgba(61, 220, 132, .8); }
.alert--info::before    { background: var(--info);   box-shadow: 0 0 12px rgba(107, 184, 255, .8); }
.alert--warning::before { background: var(--warn);   box-shadow: 0 0 12px rgba(255, 200, 107, .8); }
.alert--danger::before  { background: var(--danger); box-shadow: 0 0 12px rgba(255, 107, 107, .8); }

/* -----------------------------------------------------------------------------
   Data
   -------------------------------------------------------------------------- */

.datalist {
    display: grid;
    gap: 0;
    margin: var(--space-5) 0;
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    background: var(--surface-1);
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .06), 0 14px 34px -16px rgb(var(--shade) / calc(.8 * var(--shadow-k)));
    overflow: hidden;
}
.datalist__row {
    display: grid;
    grid-template-columns: minmax(140px, 240px) 1fr;
    gap: var(--space-4);
    padding: 13px var(--space-5);
    border-bottom: 1px solid var(--line);
    transition: background var(--t-fast) var(--ease-out);
}
.datalist__row:last-child { border-bottom: 0; }
.datalist__row:hover { background: rgb(var(--gloss) / .025); }
/* margin: 0 is not cosmetic. The list is a <dl> and the value is a <dd>, which
   every browser gives a 40px inline start margin by default. Inside a grid
   cell that margin is invisible until you wonder why the column does not line
   up with anything. */
.datalist__key { margin: 0; color: var(--text-dim); font-size: .89rem; }
.datalist__value {
    margin: 0;
    font-family: var(--mono);
    font-size: .89rem;
    color: var(--text);
    word-break: break-word;
}

.table-wrap {
    overflow-x: auto;
    margin: var(--space-5) 0;
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    background: var(--surface-1);
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .06), 0 14px 34px -16px rgb(var(--shade) / calc(.8 * var(--shadow-k)));
}
.table { width: 100%; border-collapse: collapse; font-size: .92rem; }
.table th, .table td { padding: 12px var(--space-4); text-align: left; border-bottom: 1px solid var(--line); }
.table thead th {
    position: sticky;
    top: 0;
    color: var(--text-dim);
    font-weight: 600;
    font-size: .74rem;
    text-transform: uppercase;
    letter-spacing: .1em;
    background: var(--surface-2);
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .07);
}
.table td { color: var(--text-muted); }
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover td { background: rgb(var(--gloss) / .025); }

/* Statistic tiles for the dashboards. */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--space-4); margin: var(--space-5) 0; }

.stat {
    position: relative;
    padding: var(--space-5);
    border-radius: var(--radius-lg);
    border: 1px solid var(--line);
    background:
        linear-gradient(180deg, rgb(var(--gloss) / .04), transparent 40%),
        var(--surface-1);
    box-shadow:
        inset 0 1px 0 rgb(var(--gloss) / .07),
        inset 0 -30px 60px -30px rgb(var(--gloss) / .06),
        0 12px 30px -14px rgb(var(--shade) / calc(.8 * var(--shadow-k)));
    overflow: hidden;
}
.stat__label {
    display: block;
    font-family: var(--mono);
    font-size: .72rem;
    letter-spacing: .13em;
    text-transform: uppercase;
    color: var(--text-dim);
    margin-bottom: 8px;
}
.stat__value { font-size: 1.9rem; font-weight: 700; letter-spacing: -.035em; line-height: 1.1; color: var(--text); }
.stat__note { margin: 6px 0 0; font-size: .84rem; color: var(--text-dim); }

/* -----------------------------------------------------------------------------
   Closing panel
   -------------------------------------------------------------------------- */

.cta-panel {
    position: relative;
    overflow: hidden;
    border: 1px solid transparent;
    border-radius: var(--radius-xl);
    background:
        linear-gradient(180deg, var(--surface-2), var(--surface-1) 60%, var(--surface-sunken)) padding-box,
        linear-gradient(160deg, rgba(61, 220, 132, .55), rgba(67, 208, 255, .3) 45%, rgba(169, 124, 248, .25)) border-box;
    box-shadow:
        inset 0 1px 0 rgb(var(--gloss) / .1),
        inset 0 -60px 120px -60px rgba(61, 220, 132, .28),
        0 30px 70px -28px rgb(var(--shade) / calc(.9 * var(--shadow-k)));
    padding: var(--space-8) var(--space-6);
    text-align: center;
}

/* The ruled grid behind it, masked so it never reaches an edge. */
.cta-panel::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image:
        linear-gradient(to right,  rgb(var(--gloss) / .05) 1px, transparent 1px),
        linear-gradient(to bottom, rgb(var(--gloss) / .05) 1px, transparent 1px);
    background-size: 44px 44px;
    -webkit-mask-image: radial-gradient(ellipse 80% 70% at 50% 30%, #000 10%, transparent 75%);
            mask-image: radial-gradient(ellipse 80% 70% at 50% 30%, #000 10%, transparent 75%);
}

.cta-panel > * { position: relative; z-index: 1; }
.cta-panel .section__head { margin-left: auto; margin-right: auto; }

/* Was four inline style attributes in the views, which the CSP forbids. */
.section__head--spaced { margin-top: var(--space-8); }
.section__title--sm    { font-size: var(--text-xl); }
.page__text--sm        { font-size: .9rem; }
.prose-h2--spaced      { margin-top: var(--space-7); }
.cta-panel .section__lead { margin-left: auto; margin-right: auto; }
.cta-panel .actions { justify-content: center; }

/* -----------------------------------------------------------------------------
   Narrow screens
   -------------------------------------------------------------------------- */

/* Between 860 and 1080 the labels cost more than they are worth. The tiles
   stay and carry the state, the title attribute supplies the name on hover,
   and the label text is moved out of sight rather than removed, so a screen
   reader still reads it. */
@media (min-width: 861px) and (max-width: 1080px) {
    :root { --sidebar-width: 74px; }

    .sidebar { padding: var(--space-3); align-items: stretch; }
    .sidebar__nav { gap: var(--space-3); margin: 0 calc(var(--space-3) * -1); padding: 0 var(--space-3); }
    .sidebar__section + .sidebar__section { padding-top: var(--space-3); border-top: 1px solid var(--line); }

    .sidebar__link { justify-content: center; padding: 6px 0; }
    .sidebar__link--active::before,
    .sidebar__link[aria-current='page']::before { left: calc(var(--space-3) * -1 + 4px); }

    .sidebar__switch { justify-content: center; }
    .sidebar__who { justify-content: center; }
    .sidebar__who-text { display: none; }

    .sidebar__heading,
    .sidebar__label,
    .sidebar__switch-text {
        position: absolute;
        width: 1px;
        height: 1px;
        margin: -1px;
        padding: 0;
        overflow: hidden;
        white-space: nowrap;
        clip-path: inset(50%);
    }
}

/* A link inside a table row measured 19px tall on a phone, which is a thumb
   target the width of a thumbnail. The row has 12px of padding above and below
   it, so the hit area is grown into that padding with a pseudo-element: the
   text does not move, the line height does not change, nothing reflows, and
   the tappable box clears the recommended minimum. Rows are 43px apart at
   their tightest, so two of these never overlap. */
@media (max-width: 860px) {
    .table td a,
    .stat__note a,
    .crumbs a,
    .datalist__value a { position: relative; }
    .table td a::after,
    .stat__note a::after,
    .crumbs a::after,
    .datalist__value a::after {
        content: '';
        position: absolute;
        inset: -11px -8px;
        border-radius: var(--radius-sm);
    }
}

/* The day-range switcher on the usage screen. Three buttons, one of them lit,
   rather than three digits and two middots. */
.rangeset {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    margin: var(--space-4) 0 var(--space-6);
}
.rangeset__label {
    font-family: var(--mono);
    font-size: .72rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--text-dim);
    margin-right: var(--space-1);
}
.range {
    display: inline-flex;
    align-items: center;
    min-height: 38px;
    padding: 0 15px;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-full);
    background: var(--surface-1);
    color: var(--text-muted);
    font-size: .88rem;
    font-weight: 600;
    text-decoration: none;
    transition: border-color var(--t-fast) var(--ease-out),
                background var(--t-fast) var(--ease-out),
                color var(--t-fast) var(--ease-out);
}
.range:hover { border-color: var(--line-control); background: var(--surface-2); color: var(--text); }
.range:focus-visible { outline: 2px solid var(--signal-ink); outline-offset: 2px; }
.range--on {
    border-color: var(--line-accent);
    background: rgba(61, 220, 132, .12);
    color: var(--signal-ink);
}

/* Below 860 the same markup becomes a horizontal strip above the content, so
   there is only ever one set of links to keep in step. The indicator moves
   from a left rail to an underline, because a left rail means nothing in a
   horizontal row. */
@media (max-width: 860px) {
    .layout__body {
        grid-template-columns: 1fr;
        gap: var(--space-4);
        padding-top: var(--space-4);
    }

    .sidebar {
        /* `relative`, not `static`, and it is load-bearing.
         *
         * The headings below are hidden with `position: absolute`, and an
         * absolutely positioned element is contained by its nearest POSITIONED
         * ancestor. With the sidebar static they escaped its `overflow-x` clip
         * entirely, took their static position inside the horizontal rail, and
         * landed at x=398 on a 390px screen. Result: every signed-in page
         * scrolled 9px sideways on a phone, from a box one pixel wide that
         * nobody can see. `relative` lays out identically and gives them
         * something to be clipped by.
         *
         * `top: auto` goes with it. The desktop rule sets `top: 88px` for the
         * sticky offset, and on a `relative` box that is not a threshold, it
         * is a shove: the rail moved 88px down the page and landed on top of
         * every page title in the members area and the control panel. */
        position: relative;
        top: auto;
        max-height: none;
        flex-direction: row;
        align-items: center;
        gap: var(--space-3);
        padding: var(--space-2) var(--space-3);
        overflow-x: auto;
        overscroll-behavior-x: contain;
        scrollbar-width: none;
    }
    .sidebar::-webkit-scrollbar { display: none; }

    .sidebar__nav { display: flex; gap: var(--space-3); overflow: visible; margin: 0; padding: 0; }
    .sidebar__section { display: flex; align-items: center; gap: 4px; }
    .sidebar__section + .sidebar__section { padding-left: var(--space-3); border-left: 1px solid var(--line); }
    .sidebar__list { display: flex; gap: 4px; }
    /* Clipped, not display:none: that removes the H2 from the accessibility
       tree and a screen reader user loses the grouping on a phone. The
       861-1080 block already does it this way. */
    .sidebar__heading {
        position: absolute;
        width: 1px;
        height: 1px;
        margin: -1px;
        padding: 0;
        overflow: hidden;
        white-space: nowrap;
        clip-path: inset(50%);
    }

    .sidebar__link { min-height: 40px; padding: 4px 11px; white-space: nowrap; }
    .sidebar__icon { width: 26px; height: 26px; border-radius: 8px; }

    .sidebar__link--active::before,
    .sidebar__link[aria-current='page']::before {
        left: 12px;
        right: 12px;
        top: auto;
        bottom: 2px;
        width: auto;
        height: 2px;
        border-radius: 2px;
        transform: none;
    }

    .sidebar__foot {
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 0 0 0 var(--space-3);
        border-top: 0;
        border-left: 1px solid var(--line);
    }
    .sidebar__switch { min-height: 36px; padding: 0 11px; white-space: nowrap; }
    .sidebar__who { display: none; }
}

@media (max-width: 900px) {
    .hero { grid-template-columns: 1fr; gap: var(--space-7); padding: var(--space-7) 0 var(--space-6); }
    .site-footer__inner { grid-template-columns: 1fr; gap: var(--space-6); }
}

/* The mobile navigation. Below this width the link list collapses behind the
   burger, so the header is one row at 64px instead of three wrapped rows. */
@media (max-width: 860px) {
    .nav { gap: var(--space-3); }

    .nav__burger { display: inline-flex; }

    .nav__list {
        position: absolute;
        left: 0;
        right: 0;
        top: 100%;
        flex-direction: column;
        align-items: stretch;
        gap: 2px;
        padding: var(--space-3);
        /* Opaque, and no backdrop-filter of its own. The header above it
           already has one, and a backdrop-filter nested inside another one
           establishes a backdrop root the child cannot see past: Chromium then
           composites the child's own background away and the panel renders
           see-through with the page legible behind the menu. The panel covers
           what is underneath anyway, so it has nothing to blur. */
        background: linear-gradient(180deg, var(--surface-menu-top), var(--surface-menu-foot));
        border-bottom: 1px solid var(--line-strong);
        box-shadow: 0 24px 50px -16px rgb(var(--shade) / calc(.9 * var(--shadow-k)));

        /* Collapsed. visibility keeps it out of the tab order, and the grid
           row collapse is what makes the height animate at all. */
        visibility: hidden;
        opacity: 0;
        transform: translateY(-8px);
        pointer-events: none;
        transition: opacity var(--t-base) var(--ease-out),
                    transform var(--t-base) var(--ease-out),
                    visibility 0s linear var(--t-base);
    }

    .nav__toggle:checked ~ .nav__list {
        visibility: visible;
        opacity: 1;
        transform: none;
        pointer-events: auto;
        transition-delay: 0s;
    }

    .nav__item { display: block; }
    .nav__link { width: 100%; min-height: 46px; padding: 0 14px; font-size: 1rem; }
    .nav__link::after { display: none; }
    .nav__form { width: 100%; }
    .nav__link--cta { justify-content: center; margin-top: 6px; }

    .nav__area { display: none; }

    /* Inside the collapsed panel the account menu is already behind one tap.
       Putting it behind a second would be rude, so the summary goes and the
       menu lays out in the flow. */
    .nav__item--account { margin: 6px 0 0; }
    .nav__account > summary { display: none; }
    .nav__menu {
        position: static;
        width: auto;
        border: 0;
        border-top: 1px solid var(--line);
        border-radius: 0;
        background: none;
        box-shadow: none;
        padding: var(--space-3) 0 0;
    }
    .nav__menu-link { min-height: 44px; font-size: 1rem; }
}

@media (max-width: 640px) {
    body { font-size: 16px; }
    .layout__main { padding: 0 var(--space-4) var(--space-8); }
    .layout__body { padding-left: var(--space-4); padding-right: var(--space-4); }
    .layout__main--centered { padding: var(--space-6) var(--space-4); }
    .nav { padding: 0 var(--space-4); }
    .section { padding: var(--space-8) 0; }
    .card, .feature, .plan { padding: var(--space-5) var(--space-4); }
    .card--auth { padding: var(--space-5); }
    .cta-panel { padding: var(--space-7) var(--space-4); }
    .datalist__row { grid-template-columns: 1fr; gap: 3px; padding: 12px var(--space-4); }
    .site-footer__inner, .site-footer__legal { padding-left: var(--space-4); padding-right: var(--space-4); }
    .plan--featured, .plan--featured:hover { transform: none; }
    .score { flex-wrap: wrap; }
}

/* -----------------------------------------------------------------------------
   Motion, off
   -------------------------------------------------------------------------- */

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

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

    .aurora,
    .border-beam::before,
    .shine::after,
    .btn--shimmer::after,
    .fade-in,
    .score__fill,
    .hero__pulse::after { animation: none; }

    .magic-card:hover,
    .plan:hover,
    .legal-card:hover,
    .btn:hover { transform: none; }
}

/* -----------------------------------------------------------------------------
   Print. Legal pages get printed and filed.
   -------------------------------------------------------------------------- */

@media print {
    body { background: #fff; color: #000; }
    body::before, body::after,
    .site-header, .sidebar, .site-footer__nav, .skip-link, .cta-panel { display: none; }
    .layout__body { display: block; padding: 0; }
    .prose p, .prose li, .page__lead, .page__text { color: #222; }
    .prose h2 { border-top: 1px solid #ccc; }
    a { color: #000; text-decoration: underline; }
    .card, .feature, .plan, .legal-card, .datalist, .table-wrap {
        border-color: #ccc;
        background: #fff;
        box-shadow: none;
    }
}

/* =============================================================================
   Front page, second pass
   =============================================================================

   The first version put a raw JSON block in the hero with a thin progress bar
   bolted underneath it. Two problems with that. A developer reads a response
   body as a contract, and that one was invented. And the score, which is the
   entire product, was the smallest thing on the screen.

   So the hero now shows the product: a result card of the kind the dashboard
   will render, with the score as a dial rather than a line. The JSON moved
   further down the page, where it belongs, as proof that the thing has an API
   rather than as the first thing anybody sees.
   ========================================================================== */

/* -----------------------------------------------------------------------------
   The score dial
   -------------------------------------------------------------------------- */
/* A conic gradient masked into a ring. --gauge-value is registered below, so
   it interpolates and the ring can sweep up to the score on load.

   The number in the middle is real text and never animates. The ring is
   decoration: with no fill-mode the element sits at its declared value when
   the animation has not run, so a stalled timeline shows a finished dial
   rather than an empty one. */

@property --gauge-value {
    syntax: '<number>';
    initial-value: 0;
    inherits: false;
}

.gauge {
    --gauge-size: 148px;
    --gauge-thickness: 11px;
    position: relative;
    display: grid;
    place-items: center;
    flex: none;
    width: var(--gauge-size);
    height: var(--gauge-size);
}

.gauge::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: conic-gradient(
        from 0deg,
        var(--signal)            0deg,
        var(--signal)           72deg,
        var(--warn)            162deg,
        var(--danger)          252deg,
        var(--danger)  calc(var(--gauge-value) * 3.6deg),
        rgb(var(--gloss) / .05) calc(var(--gauge-value) * 3.6deg)
    );
    -webkit-mask: radial-gradient(farthest-side,
        transparent calc(100% - var(--gauge-thickness)), #000 calc(100% - var(--gauge-thickness) + 1px));
            mask: radial-gradient(farthest-side,
        transparent calc(100% - var(--gauge-thickness)), #000 calc(100% - var(--gauge-thickness) + 1px));
    animation: gauge-sweep 1.4s var(--ease-expo);
}

/* The well the ring sits in, so it reads as cut into the card. */
.gauge::after {
    content: '';
    position: absolute;
    inset: var(--gauge-thickness);
    border-radius: 50%;
    background: var(--surface-sunken);
    box-shadow:
        inset 0 2px 10px rgb(var(--shade) / calc(.8 * var(--shadow-k))),
        inset 0 -1px 0 rgb(var(--gloss) / .05);
}

@keyframes gauge-sweep {
    from { --gauge-value: 0; }
}

.gauge__inner { position: relative; z-index: 1; text-align: center; line-height: 1; }

.gauge__value {
    display: block;
    font-family: var(--mono);
    font-size: 2.6rem;
    font-weight: 500;
    letter-spacing: -.04em;
    color: var(--text);
}

.gauge__of {
    display: block;
    margin-top: 5px;
    font-family: var(--mono);
    font-size: .64rem;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--text-dim);
}

/* Bands. The colour is a property of the verdict, not of the number. */
.gauge--clean::before  { background: conic-gradient(from 0deg, var(--signal) 0deg, var(--signal) calc(var(--gauge-value) * 3.6deg), rgb(var(--gloss) / .05) calc(var(--gauge-value) * 3.6deg)); }
.gauge--low::before    { background: conic-gradient(from 0deg, var(--signal) 0deg, var(--cyan)   calc(var(--gauge-value) * 3.6deg), rgb(var(--gloss) / .05) calc(var(--gauge-value) * 3.6deg)); }

/* -----------------------------------------------------------------------------
   The result card: what the hero shows instead of a code block
   -------------------------------------------------------------------------- */

/* -- The free check in the hero -------------------------------------------
 *
 * A form, not a widget. There is no JavaScript anywhere on this page: it
 * posts, the server answers, the card below re-renders. That is why it still
 * works with scripting off and why the CSP can stay at `default-src 'none'`.
 */

.probe {
    margin-bottom: var(--space-4);
}

.probe__label {
    display: block;
    margin-bottom: var(--space-2);
    font-size: .82rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text-dim);
}

.probe__row {
    display: flex;
    gap: var(--space-2);
    align-items: stretch;
}

.probe__input {
    flex: 1 1 auto;
    min-width: 0;
    padding: .78rem 1rem;
    font-family: var(--mono);
    font-size: 1rem;
    color: var(--text);
    background: var(--surface-sunken);
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    box-shadow: inset 0 1px 4px rgb(var(--shade) / calc(.5 * var(--shadow-k)));
    transition: border-color var(--t-base) var(--ease-out),
                box-shadow var(--t-base) var(--ease-out);
}
.probe__input::placeholder { color: var(--text-dim); }
.probe__input:focus {
    outline: none;
    border-color: var(--signal);
    box-shadow: inset 0 1px 4px rgb(var(--shade) / calc(.5 * var(--shadow-k))), 0 0 0 3px rgba(61, 220, 132, .18);
}

.probe__row .btn { flex: none; }

.probe__note {
    margin: var(--space-2) 0 0;
    font-size: .84rem;
    color: var(--text-dim);
}

.probe__error {
    margin: 0 0 var(--space-3);
    padding: .7rem .9rem;
    font-size: .9rem;
    color: var(--warn);
    background: rgba(255, 200, 107, .08);
    border: 1px solid rgba(255, 200, 107, .25);
    border-radius: var(--radius-md);
}

@media (max-width: 480px) {
    .probe__row { flex-wrap: wrap; }
    .probe__row .btn { width: 100%; }
}

.result {
    position: relative;
    overflow: hidden;
    border: 1px solid transparent;
    border-radius: var(--radius-xl);
    background:
        linear-gradient(180deg, var(--surface-2), var(--surface-1) 55%, var(--surface-sink)) padding-box,
        linear-gradient(160deg, rgba(61, 220, 132, .5), rgba(67, 208, 255, .25) 45%, rgb(var(--gloss) / .06)) border-box;
    box-shadow:
        inset 0 1px 0 rgb(var(--gloss) / .1),
        inset 0 -60px 120px -60px rgba(61, 220, 132, .18),
        0 2px 4px rgb(var(--shade) / calc(.5 * var(--shadow-k))),
        0 34px 70px -26px rgb(var(--shade) / calc(.95 * var(--shadow-k)));
}

.result__head {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--line);
    background: linear-gradient(180deg, rgb(var(--gloss) / .05), transparent);
}

.result__ip {
    font-family: var(--mono);
    font-size: 1rem;
    color: var(--text);
    letter-spacing: -.01em;
}

.result__live {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin-left: auto;
    font-family: var(--mono);
    font-size: .66rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--text-dim);
    white-space: nowrap;
}

.result__body {
    display: flex;
    align-items: center;
    gap: var(--space-5);
    padding: var(--space-5);
}

.result__verdict { min-width: 0; display: grid; gap: 10px; }

.result__band {
    justify-self: start;
    font-family: var(--mono);
    font-size: .68rem;
    font-weight: 500;
    letter-spacing: .14em;
    text-transform: uppercase;
    padding: 5px 11px;
    border-radius: var(--radius-full);
    background: rgba(255, 107, 107, .13);
    border: 1px solid rgba(255, 107, 107, .4);
    color: #ff9c9c;
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .08), 0 0 22px -8px rgba(255, 107, 107, .8);
}

.result__why { margin: 0; display: grid; gap: 7px; }

.result__reason {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: baseline;
    gap: 9px;
    font-size: .88rem;
    color: var(--text-muted);
}

.result__code {
    font-family: var(--mono);
    font-size: .7rem;
    letter-spacing: .04em;
    color: var(--signal-ink);
    background: rgba(61, 220, 132, .1);
    border: 1px solid rgba(61, 220, 132, .26);
    border-radius: 5px;
    padding: 2px 6px;
    white-space: nowrap;
}

.result__foot {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: var(--space-4) var(--space-5);
    border-top: 1px solid var(--line);
    background: var(--surface-sunken);
}

/* -----------------------------------------------------------------------------
   Trust row: the line of plain facts under the hero buttons
   -------------------------------------------------------------------------- */

.trust {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-5);
    margin: var(--space-5) 0 0;
    padding: 0;
    list-style: none;
}

.trust li {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .89rem;
    color: var(--text-muted);
}

/* An actual tick. Two crossed linear-gradients draw an X, not a check, which
   is a bad thing to put next to the word "free". */
.trust li::before {
    content: '';
    flex: none;
    width: 17px;
    height: 17px;
    border-radius: 50%;
    background: rgba(61, 220, 132, .14);
    border: 1px solid rgba(61, 220, 132, .45);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 8.4l2.6 2.6L12 5.6' fill='none' stroke='%233ddc84' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 13px 13px;
}

/* -----------------------------------------------------------------------------
   Numbered steps
   -------------------------------------------------------------------------- */

.steps {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: var(--space-5);
    counter-reset: step;
    list-style: none;
    margin: 0;
    padding: 0;
}

.step {
    counter-increment: step;
    position: relative;
    padding-top: var(--space-5);
}

.step::before {
    content: counter(step, decimal-leading-zero);
    position: absolute;
    top: 0;
    left: 0;
    font-family: var(--mono);
    font-size: .74rem;
    letter-spacing: .12em;
    color: var(--signal-ink);
}

/* The hairline that joins the steps, fading out at the last one. */
.step::after {
    content: '';
    position: absolute;
    top: 6px;
    left: 34px;
    right: calc(var(--space-5) * -1);
    height: 1px;
    background: linear-gradient(90deg, var(--line-strong), transparent);
}
.step:last-child::after { display: none; }

.step__title { font-size: 1.06rem; margin: 0 0 8px; }
.step__text { color: var(--text-muted); margin: 0; font-size: .94rem; }

/* -----------------------------------------------------------------------------
   Source marquee: the feeds behind every answer, scrolling
   -------------------------------------------------------------------------- */

.sources {
    position: relative;
    display: flex;
    gap: var(--space-4);
    overflow: hidden;
    padding: var(--space-2) 0;
    -webkit-mask-image: linear-gradient(to right, transparent, #000 10%, #000 90%, transparent);
            mask-image: linear-gradient(to right, transparent, #000 10%, #000 90%, transparent);
}

.sources__track {
    display: flex;
    flex: none;
    gap: var(--space-4);
    min-width: 100%;
    animation: sources-scroll 38s linear infinite;
}

.sources:hover .sources__track { animation-play-state: paused; }

@keyframes sources-scroll {
    from { transform: translateX(0); }
    to   { transform: translateX(calc(-100% - var(--space-4))); }
}

.source {
    display: flex;
    align-items: center;
    gap: 9px;
    flex: none;
    padding: 9px 15px;
    border-radius: var(--radius-full);
    border: 1px solid var(--line);
    background: linear-gradient(180deg, rgb(var(--gloss) / .045), rgb(var(--gloss) / .012));
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .06);
    font-size: .88rem;
    color: var(--text-muted);
    white-space: nowrap;
}

.source__dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--signal);
    box-shadow: 0 0 8px rgba(61, 220, 132, .8);
    flex: none;
}

/* -----------------------------------------------------------------------------
   Reason codes preview
   -------------------------------------------------------------------------- */

.reasons {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: 10px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.reason {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: 12px var(--space-4);
    border-radius: var(--radius-md);
    border: 1px solid var(--line);
    background: var(--surface-1);
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .05);
}

.reason__code {
    font-family: var(--mono);
    font-size: .72rem;
    letter-spacing: .03em;
    color: var(--text);
    min-width: 0;
    overflow-wrap: anywhere;
}

.reason__weight {
    margin-left: auto;
    flex: none;
    font-family: var(--mono);
    font-size: .8rem;
    font-weight: 500;
    padding: 2px 9px;
    border-radius: var(--radius-full);
}

.reason__weight--up   { color: var(--danger); background: rgba(255, 107, 107, .14); border: 1px solid rgba(255, 107, 107, .3); }
.reason__weight--down { color: var(--signal-ink); background: rgba(61, 220, 132, .12); border: 1px solid rgba(61, 220, 132, .32); }
.reason__weight--zero { color: var(--text-dim); background: rgb(var(--gloss) / .04); border: 1px solid var(--line); }

/* -----------------------------------------------------------------------------
   Score bands
   -------------------------------------------------------------------------- */
/* Four cards, one row, reading left to right as the score climbs. The left
   edge carries the band's colour so the scale is legible without reading a
   word of it. */

.bands {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: var(--space-4);
    margin: var(--space-6) 0 var(--space-5);
    padding: 0;
    list-style: none;
    counter-reset: none;
}

.band {
    position: relative;
    padding: var(--space-4) var(--space-4) var(--space-4) var(--space-5);
    border-radius: var(--radius-lg);
    border: 1px solid var(--line);
    background:
        linear-gradient(180deg, rgb(var(--gloss) / .04), transparent 40%),
        var(--surface-1);
    box-shadow:
        inset 0 1px 0 rgb(var(--gloss) / .06),
        0 12px 30px -14px rgb(var(--shade) / calc(.8 * var(--shadow-k)));
    overflow: hidden;
}

.band::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: var(--band-colour, var(--signal));
    box-shadow: 0 0 14px -2px var(--band-colour, var(--signal));
}

.band--clean  { --band-colour: #3ddc84; }
.band--low    { --band-colour: #43d0ff; }
.band--medium { --band-colour: #ffc86b; }
.band--high   { --band-colour: #ff6b6b; }

.band__range {
    display: flex;
    align-items: baseline;
    gap: 6px;
    font-family: var(--mono);
    font-size: 1.24rem;
    font-weight: 500;
    letter-spacing: -.02em;
    color: var(--band-colour, var(--text));
}

.band__to {
    font-size: .64rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--text-dim);
}

.band__name {
    margin: 8px 0 6px;
    font-size: .74rem;
    font-weight: 600;
    letter-spacing: .13em;
    text-transform: uppercase;
    color: var(--text);
}

.band__text { margin: 0; font-size: .88rem; color: var(--text-muted); }

/* -----------------------------------------------------------------------------
   FAQ, as a disclosure list. No JavaScript.
   -------------------------------------------------------------------------- */

.faq { display: grid; gap: 10px; max-width: var(--measure); }

.faq__item {
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    background: var(--surface-1);
    box-shadow: inset 0 1px 0 rgb(var(--gloss) / .05);
    overflow: hidden;
}

.faq__item[open] { border-color: var(--line-strong); }

.faq__q {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: 56px;
    padding: var(--space-3) var(--space-4);
    cursor: pointer;
    font-weight: 600;
    font-size: .98rem;
    color: var(--text);
    list-style: none;
    transition: background var(--t-fast) var(--ease-out);
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q::marker { content: ''; }
.faq__q:hover { background: rgb(var(--gloss) / .03); }
.faq__q:focus-visible { outline: 2px solid var(--signal-ink); outline-offset: -2px; }

.faq__q::after {
    content: '';
    flex: none;
    margin-left: auto;
    width: 9px;
    height: 9px;
    border-right: 1.8px solid var(--text-dim);
    border-bottom: 1.8px solid var(--text-dim);
    transform: rotate(45deg) translate(-2px, -2px);
    transition: transform var(--t-base) var(--ease-out);
}
.faq__item[open] .faq__q::after { transform: rotate(-135deg) translate(-2px, -2px); }

.faq__a { padding: 0 var(--space-4) var(--space-4); color: var(--text-muted); font-size: .94rem; }
.faq__a p { margin: 0 0 .7em; }
.faq__a p:last-child { margin-bottom: 0; }

/* -----------------------------------------------------------------------------
   Narrow screens, for everything above
   -------------------------------------------------------------------------- */

@media (max-width: 640px) {
    .gauge { --gauge-size: 118px; --gauge-thickness: 9px; }
    .gauge__value { font-size: 2rem; }
    .result__body { flex-direction: column; align-items: stretch; gap: var(--space-4); }
    .gauge { justify-self: center; margin: 0 auto; }
    .step::after { display: none; }
    .step { padding-left: 34px; padding-top: 0; }
    .step::before { top: 2px; }
}

/* -----------------------------------------------------------------------------
   Developer page
   --------------------------------------------------------------------------
   A reference is read in two ways: front to back, once, and then dipped into
   forever afterwards. The second one is what the layout serves. Endpoints are
   cards with the method and the path in the header, so scrolling past finds
   the right one without reading anything.

   No JavaScript, here as everywhere else on this site. The spec that a tool
   would consume lives at /openapi.json; this is the version for a person, and
   a person does not need a megabyte of framework to read a table. */

.page--dev .page__lead { max-width: var(--measure); }

.dev-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-top: var(--space-6);
}

.dev-h2 {
    margin: var(--space-9) 0 var(--space-4);
    font-size: var(--text-2xl);
    font-weight: 600;
    letter-spacing: -.02em;
    color: var(--text);
    scroll-margin-top: var(--space-8);
}

.dev-lead {
    max-width: var(--measure);
    margin: 0 0 var(--space-6);
    color: var(--text-muted);
}

.dev-note {
    margin-top: var(--space-3);
    font-size: .9rem;
    color: var(--text-dim);
}

.dev-h3 {
    margin: var(--space-7) 0 var(--space-3);
    font-size: var(--text-lg);
    font-weight: 600;
    letter-spacing: -.01em;
    color: var(--text);
}

/* -- The two keys, side by side, because the difference is the whole model -- */

.dev-keys {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: var(--space-4);
    margin-top: var(--space-7);
}

.dev-key {
    padding: var(--space-5);
    background: var(--surface-1);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
}

.dev-key p {
    margin: var(--space-3) 0 0;
    font-size: .92rem;
    color: var(--text-muted);
}

.dev-key__tag {
    display: inline-block;
    padding: 3px 9px;
    border-radius: var(--radius-full);
    font-family: var(--mono);
    font-size: .68rem;
    letter-spacing: .1em;
    text-transform: uppercase;
}

.dev-key__tag--public { background: rgba(67, 208, 255, .13); color: var(--cyan-ink); }
.dev-key__tag--secret { background: rgba(255, 107, 107, .13); color: var(--danger); }

.dev-key__code {
    display: block;
    margin-top: var(--space-3);
    font-family: var(--mono);
    font-size: 1rem;
    color: var(--text);
}

/* -- Numbered steps -------------------------------------------------------- */

.dev-steps {
    margin: 0;
    padding: 0;
    list-style: none;
    counter-reset: dev-step;
}

.dev-step {
    position: relative;
    counter-increment: dev-step;
    padding: 0 0 var(--space-7) var(--space-7);
    border-left: 1px solid var(--line);
}

.dev-step:last-child { border-left-color: transparent; padding-bottom: 0; }

.dev-step::before {
    content: counter(dev-step);
    position: absolute;
    left: calc(var(--space-3) * -1 - 1px);
    top: 0;
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--surface-2);
    border: 1px solid var(--line-strong);
    font-family: var(--mono);
    font-size: .76rem;
    color: var(--signal-ink);
}

.dev-step__title {
    margin: 0 0 var(--space-2);
    font-size: var(--text-lg);
    font-weight: 600;
}

.dev-step p { margin: 0 0 var(--space-3); color: var(--text-muted); }
.dev-step .code { margin: var(--space-3) 0; }

/* -- The four reliability cards -------------------------------------------- */

.dev-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: var(--space-4);
    margin-bottom: var(--space-6);
}

.dev-card {
    padding: var(--space-5);
    background: var(--surface-1);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
}

.dev-card__title {
    margin: 0 0 var(--space-2);
    font-size: 1rem;
    font-weight: 600;
    color: var(--text);
}

.dev-card p { margin: 0; font-size: .92rem; color: var(--text-muted); }

/* -- One endpoint ---------------------------------------------------------- */

.endpoint {
    margin: var(--space-5) 0;
    background: var(--surface-1);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    overflow: hidden;
    scroll-margin-top: var(--space-8);
}

.endpoint__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    background: var(--surface-2);
    border-bottom: 1px solid var(--line);
}

.endpoint__method {
    padding: 3px 9px;
    border-radius: var(--radius-sm);
    font-family: var(--mono);
    font-size: .72rem;
    font-weight: 500;
    letter-spacing: .08em;
}

.endpoint__method--post   { background: rgba(61, 220, 132, .15); color: var(--signal-ink); }
.endpoint__method--get    { background: rgba(67, 208, 255, .15); color: var(--cyan-ink); }
.endpoint__method--delete { background: rgba(255, 107, 107, .15); color: var(--danger); }

.endpoint__path {
    font-family: var(--mono);
    font-size: .92rem;
    color: var(--text);
    word-break: break-all;
}

.endpoint__auth {
    margin-left: auto;
    padding: 3px 9px;
    border-radius: var(--radius-full);
    font-size: .72rem;
    white-space: nowrap;
}

.endpoint__auth--public { background: rgba(67, 208, 255, .1); color: var(--cyan-ink); }
.endpoint__auth--secret { background: rgba(255, 107, 107, .1); color: var(--danger); }

.endpoint__body { padding: var(--space-5); }

.endpoint__title {
    margin: 0 0 var(--space-3);
    font-size: var(--text-lg);
    font-weight: 600;
}

.endpoint__h4 {
    margin: var(--space-5) 0 var(--space-3);
    font-family: var(--mono);
    font-size: .7rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--text-dim);
}

.endpoint .code { margin: 0; }
.endpoint .table { font-size: .88rem; }
.endpoint .table code { font-size: .86em; }

.prose--tight { max-width: var(--measure); }
.prose--tight p { margin: 0 0 .7em; }
.prose--tight p:last-child { margin-bottom: 0; }

.pill {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 6px;
    border-radius: var(--radius-full);
    font-size: .66rem;
    letter-spacing: .04em;
    vertical-align: middle;
}

.pill--req { background: rgba(255, 200, 107, .14); color: var(--warn); }

.dev-enum {
    display: block;
    margin-top: 3px;
    font-family: var(--mono);
    font-size: .76rem;
    color: var(--text-dim);
}

.callout__title {
    margin: 0 0 var(--space-2);
    font-size: 1rem;
    font-weight: 600;
    color: var(--text);
}

@media (max-width: 640px) {
    .endpoint__auth { margin-left: 0; }
    .dev-step { padding-left: var(--space-5); }
}

/* -----------------------------------------------------------------------------
   Members area
   --------------------------------------------------------------------------
   Mostly reuse: the dashboard tiles are .stat, the quota bar is .score__meter
   with the same width-step classes the front page uses, and the plan cards are
   the pricing cards. What follows is only what the account screens genuinely
   add. */

.stat__unit { font-size: .9rem; font-weight: 400; color: var(--text-dim); letter-spacing: 0; }

/* -----------------------------------------------------------------------------
   The key screen
   --------------------------------------------------------------------------
   The one screen on this site with a single-chance moment on it: a freshly
   minted key is readable once and never again, so the panel that shows it owns
   the top of the page and everything else moves down.

   No JavaScript, here as everywhere. That rules out a copy button, so the
   affordances are the ones the browser already gives: the key sits in a
   `readonly` input, which focuses on click and selects on Ctrl-A like every
   field anybody has ever used, rather than in a `<pre>` slab that selects the
   whole page with it. Choosing the kind of key is two radios rather than a
   dropdown, because the choice decides whether a secret ends up in a web page
   and a dropdown hides that behind a click. */

.minted {
    position: relative;
    margin: 0 0 var(--space-7);
    padding: var(--space-6);
    max-width: var(--measure);
    border: 1px solid var(--line-accent);
    border-radius: var(--radius-xl);
    background:
        radial-gradient(120% 100% at 0% 0%, rgba(61, 220, 132, .09), transparent 55%),
        var(--surface-1);
    box-shadow:
        inset 0 1px 0 rgb(var(--gloss) / .05),
        0 24px 60px -24px rgb(var(--shade) / calc(.8 * var(--shadow-k)));
}

.minted__title {
    margin: 0 0 var(--space-3);
    font-size: var(--text-xl);
    font-weight: 600;
    letter-spacing: -.02em;
    color: var(--text);
}

.minted__lead {
    margin: 0 0 var(--space-5);
    color: var(--text-muted);
    font-size: var(--text-sm);
    line-height: 1.6;
}

.minted__label {
    display: block;
    margin-bottom: var(--space-2);
    font-size: .87rem;
    font-weight: 600;
    color: var(--text);
}

/* The field the key lives in. Mono, because a key is read character by
   character when somebody is checking they pasted the right one, and
   proportional type turns l, 1 and I into the same glyph. */
.minted__value {
    display: block;
    width: 100%;
    padding: 13px 14px;
    border: 1px solid var(--line-accent);
    border-radius: var(--radius-md);
    background: var(--surface-sunken);
    color: var(--text);
    font-family: var(--mono);
    /* A key is exactly 40 characters, always, and the whole point of this box
       is that all 40 are readable. A fixed size that fits on a desktop hides
       the last two on a phone, behind a scroll nobody looks for, and a key
       copied two characters short fails with a message about authentication.
       So the type shrinks with the viewport and stops at a size a desktop can
       still read comfortably. */
    font-size: clamp(.68rem, 2.6vw, .88rem);
    line-height: 1.4;
    box-shadow: inset 0 2px 10px rgb(var(--shade) / calc(.55 * var(--shadow-k)));
}
.minted__value:hover { border-color: rgba(61, 220, 132, .55); }
.minted__value:focus {
    outline: none;
    border-color: var(--signal);
    box-shadow:
        inset 0 2px 10px rgb(var(--shade) / calc(.55 * var(--shadow-k))),
        0 0 0 3px rgba(61, 220, 132, .18);
}
.minted__value:focus-visible { outline: 2px solid var(--signal-ink); outline-offset: 2px; }

/* The ready-made command wraps rather than scrolls. In an input the end of the
   line sits behind a scroll nobody notices, and the end of a curl line is the
   part that says what is being looked up. */
textarea.minted__value--cmd {
    border-color: var(--line-strong);
    color: var(--text-muted);
    font-size: clamp(.68rem, 2.4vw, .82rem);
    white-space: pre-wrap;
    word-break: break-all;
    resize: vertical;
}
textarea.minted__value--cmd:hover { border-color: var(--line-control); }

.minted__hint,
.minted__next {
    margin: var(--space-2) 0 0;
    font-size: .82rem;
    color: var(--text-dim);
}
.minted__next { margin-top: var(--space-5); color: var(--text-muted); }

/* The form. Narrow on purpose: a full-width form on a 1440px screen reads as
   an admin tool, and this one is a customer's first five minutes. */
/* `.form` is a grid, which stretches a lone button across the whole column.
   A 45rem-wide Create button reads as a dialogue somebody forgot to close. */
.keyform { max-width: var(--measure); margin: 0 0 var(--space-6); }
.keyform > .btn { justify-self: start; }

/* The headings on this screen separate three short blocks, not three chapters,
   so they do not need the 96px the reference page gives them. */
.page--keys .dev-h2 { margin-top: var(--space-6); }
.page--keys .dev-h2:first-of-type { margin-top: 0; }
.keyform .field { margin-bottom: var(--space-2); }
.keyform textarea.field__input { font-family: var(--mono); font-size: .86rem; resize: vertical; }

.keyform__kinds {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: var(--space-3);
    margin: 0 0 var(--space-5);
    padding: 0;
    border: 0;
}
.keyform__kinds .field__label { margin-bottom: var(--space-3); padding: 0; }

/* One choice, as a card. The native radio is kept and shown: it is the control
   screen readers announce, it is what the keyboard drives, and a hand-drawn
   replacement would have to reimplement all of that to look marginally
   better. `accent-color` is enough to stop it looking like 1997. */
.kind {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: start;
    gap: var(--space-3);
    padding: var(--space-4);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-lg);
    background: var(--surface-1);
    cursor: pointer;
    transition: border-color var(--t-fast) var(--ease-out),
                background var(--t-fast) var(--ease-out);
}
.kind:hover { border-color: var(--line-control); background: var(--surface-2); }

.kind__radio {
    width: 17px;
    height: 17px;
    margin: 3px 0 0;
    accent-color: var(--signal);
    cursor: pointer;
}

.kind__body { display: block; }

.kind__name {
    display: block;
    font-size: .97rem;
    font-weight: 600;
    color: var(--text);
}

.kind__code {
    display: block;
    margin: 3px 0 var(--space-2);
    font-family: var(--mono);
    font-size: .78rem;
    color: var(--signal-ink);
}

.kind__what {
    display: block;
    font-size: .84rem;
    line-height: 1.55;
    color: var(--text-muted);
}

.kind:has(.kind__radio:checked) {
    border-color: var(--line-accent);
    background:
        linear-gradient(180deg, rgba(61, 220, 132, .06), transparent 60%),
        var(--surface-2);
}
.kind:focus-within { outline: 2px solid var(--signal-ink); outline-offset: 2px; }

/* The websites box belongs to the publishable key and is meaningless for the
   other one, so it is hidden while the other one is chosen.

   Written this way round on purpose. A browser too old for `:has()` gets the
   field with its explanation, which is the old behaviour and still correct;
   written the other way round, that same browser would get a required field
   it could never see. */
.keyform:has(.kind__radio[value="secret"]:checked) .keyform__origins { display: none; }

/* Revoking sits behind a disclosure, because one stray click on the wrong row
   takes down somebody's checkout and there is no undo. */
.revoke { display: inline-block; }
.revoke > summary { list-style: none; }
.revoke > summary::-webkit-details-marker { display: none; }
.revoke > summary::marker { content: ''; }

.revoke__body {
    margin-top: var(--space-3);
    padding: var(--space-4);
    max-width: 22rem;
    border: 1px solid rgba(255, 107, 107, .3);
    border-radius: var(--radius-md);
    background: var(--surface-2);
    white-space: normal;
}
.revoke__body p {
    margin: 0 0 var(--space-3);
    font-size: .82rem;
    line-height: 1.55;
    color: var(--text-muted);
}

/* The label is `--danger` itself, not a pale tint of it.
 *
 * It was #ffc2c2, which is a fine colour on a dark card and 1.45:1 on a white
 * one: in the light palette the destructive button became the least readable
 * control on the page. The token moves with the theme and the fill moves with
 * it, so the pair is contrasty in both. */
.btn--danger {
    border-color: var(--line-danger);
    background: var(--surface-danger);
    color: var(--danger);
    box-shadow: none;
}
.btn--danger:hover {
    border-color: var(--danger);
    background: var(--surface-danger-strong);
    color: var(--danger);
}

@media (max-width: 640px) {
    .minted { padding: var(--space-5) var(--space-4); }
    .minted__value { padding: 12px 11px; }

    /* Six columns do not fit on a phone, and the usual answer, a sideways
       scroll, hides the Revoke button off the right edge of a list whose whole
       purpose is revoking things. So each key becomes a card and the column
       headings become row labels. The `data-label` attributes are on the cells
       in the markup; nothing here invents them. */
    .page--keys .table-wrap {
        overflow: visible;
        border: 0;
        background: none;
        box-shadow: none;
        display: grid;
        gap: var(--space-3);
    }
    .page--keys .table,
    .page--keys .table tbody,
    .page--keys .table tr,
    .page--keys .table td { display: block; width: auto; }

    .page--keys .table thead { display: none; }

    .page--keys .table tr {
        padding: var(--space-4);
        border: 1px solid var(--line);
        border-radius: var(--radius-lg);
        background: var(--surface-1);
        box-shadow: inset 0 1px 0 rgb(var(--gloss) / .06);
    }
    .page--keys .table tr + tr { margin-top: var(--space-3); }

    .page--keys .table td {
        display: grid;
        grid-template-columns: 6.5rem 1fr;
        align-items: baseline;
        gap: var(--space-3);
        padding: 6px 0;
        border-bottom: 0;
    }
    .page--keys .table td::before {
        content: attr(data-label);
        color: var(--text-dim);
        font-size: .72rem;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: .09em;
    }

    /* The action cell carries no label and gets the full width, so the button
       is a full-width target rather than a 70px one in a 6.5rem gutter. */
    .page--keys .table td.cell--act {
        display: block;
        margin-top: var(--space-3);
        padding-top: var(--space-3);
        border-top: 1px solid var(--line);
    }
    .page--keys .revoke,
    .page--keys .revoke__body { display: block; max-width: none; width: 100%; }
    /* `flex`, not `block`: `.btn` centres its label with flex alignment, and a
       block summary left-aligns the word inside a full-width button. */
    .page--keys .revoke > summary,
    .page--keys .revoke__body .btn { display: flex; width: 100%; white-space: normal; }
}

.btn--small {
    padding: 5px 11px;
    font-size: .8rem;
    border-radius: var(--radius-sm);
}

/* A revoked key is still worth showing, and worth showing as finished. */
.row--dim td { opacity: .5; }
.row--dim code { text-decoration: line-through; }

/* The bar column on the usage table carries no text, so it may shrink. */
.cell--bar { width: 30%; min-width: 90px; }
.cell--bar .score__meter { min-width: 60px; }

/* A callout that is good news. The warn variant already exists; this is its
   opposite, for a payment that went through and a key that was just made. */
.callout--signal { background: linear-gradient(90deg, rgba(61, 220, 132, .07), transparent 40%), var(--surface-1); }
.callout--signal::before { background: linear-gradient(180deg, var(--signal), var(--cyan)); box-shadow: 0 0 14px rgba(61, 220, 132, .6); }
.callout--signal .code { margin: var(--space-3) 0 0; }

/* The plan you are already on is not a thing to buy. */
.plan--current { border-color: var(--line-accent); }
.plan__current {
    margin: var(--space-4) 0 0;
    font-family: var(--mono);
    font-size: .72rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--signal-ink);
}

.page--billing .plan form,
.page--billing .plan__current { margin-top: auto; padding-top: var(--space-4); }
.page--billing .plan { display: flex; flex-direction: column; }

/* -----------------------------------------------------------------------------
   Control panel
   --------------------------------------------------------------------------
   A health check is read at a glance and usually in a hurry, so state is
   carried by a coloured dot AND by a word. Colour alone fails for anybody who
   cannot distinguish red from green, and this is the screen where being wrong
   about whether something is broken costs the most. */

.checks { display: grid; gap: var(--space-3); margin-bottom: var(--space-6); }

.check {
    display: flex;
    align-items: flex-start;
    gap: var(--space-4);
    padding: var(--space-4) var(--space-5);
    background: var(--surface-1);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
}

.check__dot {
    flex: none;
    width: 10px;
    height: 10px;
    margin-top: 6px;
    border-radius: 50%;
    background: var(--text-dim);
}

.check--ok   { border-left: 3px solid var(--signal); }
.check--warn { border-left: 3px solid var(--warn); }
.check--bad  { border-left: 3px solid var(--danger); }

.check--ok   .check__dot { background: var(--signal); box-shadow: 0 0 10px rgba(61, 220, 132, .7); }
.check--warn .check__dot { background: var(--warn);   box-shadow: 0 0 10px rgba(255, 200, 107, .7); }
.check--bad  .check__dot { background: var(--danger); box-shadow: 0 0 10px rgba(255, 107, 107, .7); }

.check__body { min-width: 0; }
.check__name { margin: 0 0 3px; font-size: .96rem; font-weight: 600; color: var(--text); }
.check__detail { margin: 0; font-size: .88rem; color: var(--text-muted); }

.badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: var(--radius-full);
    font-family: var(--mono);
    font-size: .72rem;
    letter-spacing: .06em;
    text-transform: uppercase;
}

.badge--ok    { background: rgba(61, 220, 132, .14); color: var(--signal-ink); }
.badge--warn  { background: rgba(255, 200, 107, .14); color: var(--warn); }
.badge--late  { background: rgba(255, 200, 107, .14); color: var(--warn); }
.badge--bad   { background: rgba(255, 107, 107, .14); color: var(--danger); }
.badge--never { background: rgb(var(--gloss) / .07); color: var(--text-dim); }

/* A failed run in a list of successful ones. Tinted rather than reddened all
   over: the row still has to be readable, and a red row of red text is not. */
.row--bad td { background: rgba(255, 107, 107, .05); }
.row--bad td:first-child { box-shadow: inset 2px 0 0 var(--danger); }

/* What a task said when it failed, which is the whole reason this screen
   exists, so it is not truncated. It is the only cell allowed to wrap and it
   is capped so one stack trace cannot push the table off the screen. */
.cell--said {
    max-width: 34rem;
    white-space: normal;
    word-break: break-word;
    font-family: var(--mono);
    font-size: .82rem;
    line-height: 1.5;
}

/* -- The two-factor setup panel -------------------------------------------
 *
 * The QR code is a data URI on a white plate. White, not the surface colour:
 * a scanner thresholds light against dark, and a code rendered on the dark
 * page background reads as inverted by roughly half of them. The plate is what
 * makes it scannable on a dark theme.
 */

.totp {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-6);
    align-items: flex-start;
    margin: var(--space-5) 0 var(--space-7);
}

.totp__qr {
    flex: none;
    width: 246px;
    height: 246px;
    max-width: 100%;
    padding: var(--space-3);
    background: #fff;
    border-radius: var(--radius-md);
    box-shadow: 0 18px 40px -20px rgb(var(--shade) / calc(.8 * var(--shadow-k)));
}

.totp__manual { flex: 1 1 260px; min-width: 0; }

.totp__secret {
    margin: 0 0 var(--space-2);
    font-family: var(--mono);
    font-size: 1rem;
    letter-spacing: .06em;
    word-break: break-all;
}

/* A short field and its button on one line, stacking on a phone. */
.form--row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: flex-end;
    margin-bottom: var(--space-6);
}
.form--row .field { flex: 1 1 220px; min-width: 0; margin: 0; }

/* -- Control panel listings ------------------------------------------------ */

.pager {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: center;
    margin: var(--space-5) 0 var(--space-7);
}
.pager__count { font-size: .88rem; color: var(--text-dim); }

.filters { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: 0 0 var(--space-5); }
.filters .btn.is-on { border-color: var(--signal); color: var(--signal-ink); }

/* A control that is present so the row does not reflow, and does nothing. */
.btn.is-disabled { opacity: .4; pointer-events: none; }

.callout__list { margin: var(--space-2) 0 0; padding-left: 1.1rem; color: var(--text-muted); font-size: .95rem; }
.callout__list li + li { margin-top: .4em; }

/* A cell that carries a value and a quieter second line under it. */
.table .dev-enum { display: block; margin-top: 2px; }

/* Maintenance buttons: one per table row, plus a standing control under it. */
.run { margin: 0; }
.run-row { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; margin-top: var(--space-4); }
.run-row--spaced { margin: var(--space-5) 0 var(--space-7); }
.run-row__note { margin: 0; flex: 1 1 260px; min-width: 0; }

/* Two payment buttons in one table cell, wrapping rather than overflowing. */
.buy-row { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.buy-row form { margin: 0; }
