/* Kesvara.
 *
 * Mobile-first and single-column by default; the two-column layouts are the
 * exception, added at a min-width and never assumed. Written that way round
 * because the reverse -- a desktop grid squeezed down with overrides -- is
 * how a 320px right-hand rail ends up hanging off the side of a phone.
 *
 * Tap targets are 44px minimum. tests/mobile_layout.mjs fails the build when
 * one is under 40, and it has failed for real.
 */

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

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--ink);
    font: var(--step-0)/1.65 var(--sans);
    /* The single most common cause of a sideways-scrolling page: a long
     * unbroken token -- a hostname, a fingerprint, a stack frame -- that no
     * amount of flexbox can shrink. This product is full of them. */
    overflow-wrap: break-word;
}

a { color: var(--accent); text-underline-offset: 2px; }
a:hover { text-decoration-thickness: 2px; }

h1, h2, h3 { line-height: 1.2; margin: 0 0 var(--sp-2); font-weight: 650;
             letter-spacing: -0.01em; }
h1 { font-size: var(--step-3); }
h2 { font-size: var(--step-2); margin-top: var(--sp-5); }
h3 { font-size: var(--step-1); margin-top: var(--sp-4); }
p  { margin: 0 0 var(--sp-3); }

code, kbd, pre { font-family: var(--mono); font-size: 0.92em; }
code { background: var(--surface-2); border: 1px solid var(--line-soft);
       border-radius: var(--radius-sm); padding: 0.1em 0.35em; }
pre  { background: var(--surface); border: 1px solid var(--line);
       border-radius: var(--radius); padding: var(--sp-3);
       overflow-x: auto; margin: 0 0 var(--sp-3); }
pre code { background: none; border: 0; padding: 0; }

/* A whole program, meant to be copied. It must NOT be re-wrapped: a soft wrap
   in a code block puts an apparent line break where the language does not
   allow one, and the reader cannot tell which breaks are real. So it scrolls
   inside its own box -- `max-width: 100%` is the part that matters, because a
   pre that sizes to its widest line will otherwise widen the whole page and
   every phone gets a horizontal scrollbar on the document. */
.code-block { max-width: 100%; overflow-x: auto; white-space: pre; }

.skip { position: absolute; left: -9999px; }
.skip:focus { left: var(--sp-3); top: var(--sp-3); z-index: 20;
              background: var(--accent); color: var(--accent-ink);
              padding: var(--sp-2) var(--sp-3); border-radius: var(--radius); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px;
                 border-radius: var(--radius-sm); }

.wrap { width: 100%; max-width: var(--wrap); margin: 0 auto;
        padding-inline: var(--sp-3); }
.prose { max-width: var(--prose); }
.muted { color: var(--muted); }
.faint { color: var(--faint); font-size: var(--step--1); }
.mono  { font-family: var(--mono); }
.nowrap-scroll { overflow-x: auto; }

/* ------------------------------------------------------------- header --- */
.site-head { border-bottom: 1px solid var(--line);
             background: color-mix(in srgb, var(--bg) 85%, transparent);
             position: sticky; top: 0; z-index: 10;
             backdrop-filter: blur(8px); }
.head-row { display: flex; align-items: center; gap: var(--sp-3);
            min-height: 64px; flex-wrap: wrap; }
/* The SN-01 lockup. The frame's values: 14px, -.01em, a 7x14px accent block
   at 1.5px radius with an 8px left margin, and the slash in the line colour
   with 7px either side. `gap` is 0 between the words because the frame spaces
   them with that margin rather than evenly. */
.brand { display: inline-flex; align-items: center; gap: 0;
         font-size: 0.875rem; letter-spacing: -0.01em;
         color: var(--ink); text-decoration: none; }
.brand-mark { flex: none; margin-right: 0.5rem; }
.brand-suite { font-weight: 600; }
/* The frame draws this slash in its line colour, #3A3A3F, which is 1.71:1
   and unreadable. It is --faint here — the second measured deviation from
   SN-01 and the same one as the first: a colour the frame uses decoratively
   that this site will not print as text. It is a separator between two words
   and is `aria-hidden`, so nothing is lost by it being legible. */
.brand-slash { color: var(--faint); margin: 0 7px; }
.brand-product { color: var(--muted); }
.brand-block { display: inline-block; width: 7px; height: 14px; flex: none;
               background: var(--accent); border-radius: 1.5px;
               margin-left: 8px; }
.head-nav { margin-left: auto; display: flex; align-items: center;
            gap: var(--sp-1); flex-wrap: wrap; }
.head-nav a { color: var(--muted); text-decoration: none;
              font-size: 0.84rem;
              padding: 0.6rem 0.6rem; border-radius: var(--radius-sm);
              font-size: var(--step--1); min-height: 44px;
              display: inline-flex; align-items: center; }
.head-nav a:hover { color: var(--ink); background: var(--surface); }
/* The nav's call to action is a BUTTON that happens to be an <a> inside the
   nav, and `.head-nav a` out-specifies `.btn-primary` — so it shipped with
   muted text on the accent fill at 1.94:1, which no test here could see and
   which is obvious the moment somebody looks at the page. Found by taking a
   screenshot of the deployed site rather than by asserting anything. */
.head-nav a.btn-primary { color: var(--accent-ink); }
.head-nav a.btn-primary:hover { color: var(--accent-ink);
                                background: var(--accent); }

/* ------------------------------------------------------------ buttons --- */
.btn {
    display: inline-flex; align-items: center; justify-content: center;
    gap: 0.45rem;
    min-height: 44px; padding: 0.6rem 1.05rem;
    border-radius: var(--radius); border: 1px solid var(--line);
    background: var(--surface-2); color: var(--ink);
    font: inherit; font-weight: 560; text-decoration: none;
    cursor: pointer;
}
.btn:hover { border-color: var(--accent); }
.btn-primary { background: var(--accent); color: var(--accent-ink);
               border-color: var(--accent); font-weight: 640; }
.btn-primary:hover { filter: brightness(1.08); }
.btn-quiet { background: none; border-color: transparent; color: var(--muted); }
.btn-quiet:hover { color: var(--ink); background: var(--surface); }
.btn-sm { min-height: 44px; padding: 0.45rem 0.8rem;
          font-size: var(--step--1); }
.btn[disabled] { opacity: 0.5; cursor: not-allowed; }

/* -------------------------------------------------------------- forms --- */
label { display: block; font-weight: 560; margin-bottom: var(--sp-1);
        font-size: var(--step--1); }
input[type=text], input[type=email], input[type=password], input[type=url],
textarea, select {
    width: 100%; min-height: 44px;
    padding: 0.6rem 0.75rem;
    background: var(--bg); color: var(--ink);
    border: 1px solid var(--line); border-radius: var(--radius);
    font: inherit;
    /* 16px minimum, or iOS Safari zooms the page on focus and the person is
     * left scrolled sideways on a form they were trying to fill in. */
    font-size: max(1rem, var(--step-0));
}
textarea { min-height: 8rem; resize: vertical; line-height: 1.5; }
input:focus, textarea:focus { border-color: var(--accent); }
.field { margin-bottom: var(--sp-3); }
.hint { color: var(--muted); font-size: var(--step--1); margin-top: var(--sp-1); }

.notice { border-radius: var(--radius); padding: var(--sp-2) var(--sp-3);
          margin-bottom: var(--sp-3); border: 1px solid var(--line);
          background: var(--surface); font-size: var(--step--1); }
.notice-error { border-color: var(--warn); background: var(--warn-bg);
                color: #ffd9cc; }
.notice-ok { border-color: var(--resolved); background: var(--resolved-bg); }

/* -------------------------------------------------------------- cards --- */
.card { background: var(--surface); border: 1px solid var(--line);
        border-radius: var(--radius); padding: var(--sp-3);
        margin-bottom: var(--sp-3); }
.card-tight { padding: var(--sp-2) var(--sp-3); }

.pill { display: inline-flex; align-items: center; gap: 0.35rem;
        padding: 0.15rem 0.55rem; border-radius: 999px;
        font-size: var(--step--1); font-weight: 560;
        border: 1px solid var(--line); background: var(--surface-2);
        color: var(--muted); }
.pill-open { color: var(--open); background: var(--open-bg);
             border-color: color-mix(in srgb, var(--open) 40%, transparent); }
.pill-resolved { color: var(--resolved); background: var(--resolved-bg);
                 border-color: color-mix(in srgb, var(--resolved) 40%, transparent); }
/* Provenance, not status. Deliberately the quietest pill on the site: an
   imported incident is a real record of the team's own history and the mark is
   a qualification, not a warning. Colouring it like a fault would tell people
   to distrust rows they are right to rely on. */
.pill-quiet { color: var(--faint); background: transparent; }

.row { display: flex; gap: var(--sp-2); align-items: center; flex-wrap: wrap; }
.row-between { display: flex; gap: var(--sp-2); align-items: baseline;
               flex-wrap: wrap; justify-content: space-between; }
.stack > * + * { margin-top: var(--sp-2); }

/* Two columns only where there is room. Never the other way round. */
.split { display: grid; gap: var(--sp-3); }
@media (min-width: 56rem) {
    .split { grid-template-columns: minmax(0, 1fr) minmax(0, 20rem); }
}
.split > * { min-width: 0; }   /* without this a grid child refuses to shrink */

.list { list-style: none; margin: 0; padding: 0; }
.list li + li { margin-top: var(--sp-2); }

.inc-link { display: block; text-decoration: none; color: inherit;
            border: 1px solid var(--line); border-radius: var(--radius);
            background: var(--surface); padding: var(--sp-3); }
.inc-link:hover { border-color: var(--accent); }
.inc-title { font-weight: 600; margin-bottom: var(--sp-1); }

.terms { display: flex; flex-wrap: wrap; gap: 0.3rem; margin: var(--sp-2) 0 0; }
.term { font-family: var(--mono); font-size: var(--step--1);
        background: var(--surface-2); border: 1px solid var(--line-soft);
        border-radius: var(--radius-sm); padding: 0.1rem 0.4rem;
        color: var(--muted); }

/* Tickable words on /drift. Wraps rather than scrolls: these are the thing the
 * person is being asked to act on, and a horizontally-scrolled row of them
 * hides half the choice on a phone. The tap target is the whole chip, not the
 * 13px box — this is a page somebody uses one-handed. */
.term-pick { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.term-check { display: inline-flex; align-items: center; gap: 0.35rem;
              padding: 0.35rem 0.5rem; cursor: pointer; min-height: 2rem; }
.term-check input { margin: 0; }
.term-check:has(input:checked) { border-color: var(--accent);
                                 background: var(--surface); color: var(--fg); }
.term-check:focus-within { outline: 2px solid var(--accent);
                           outline-offset: 1px; }

/* "Was this the same failure?" at the foot of every suggestion. Ruled off
 * rather than boxed: it is a question about the card above it, and a box would
 * read as another claim in the stack of claims. */
.judge { margin-top: var(--sp-3); padding-top: var(--sp-3);
         border-top: 1px solid var(--line-soft); }

/* Two answers, side by side where there is room and stacked where there is
 * not. `wrap` and not a media query: the constraint is the width of the CARD,
 * which is half the page on a desktop split view and all of it on a phone, so
 * a viewport breakpoint would get the split-view case wrong. */
.judge-buttons { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

/* The dismissed-suggestion summary. `list-style` is left alone so the
 * disclosure triangle stays — it is the only affordance saying the thing
 * reopens, and a dismissal you cannot look inside is one nobody can check. */
details.card > summary { font-size: var(--step--1); }
details.card > summary::marker { color: var(--faint); }

/* The line that carries the honest law. It is not decoration; it appears next
 * to every suggestion and must survive a skim. */
.law { border-left: 3px solid var(--accent); padding-left: var(--sp-3);
       color: var(--muted); font-size: var(--step--1); margin: var(--sp-3) 0; }

/* -------------------------------------------------------------- table --- */
/* Wrapped in .nowrap-scroll so a wide table scrolls ITSELF rather than making
 * the whole document scroll sideways. */
table { border-collapse: collapse; width: 100%; font-size: var(--step--1); }
th, td { text-align: left; padding: 0.55rem 0.7rem;
         border-bottom: 1px solid var(--line-soft); vertical-align: top; }
th { color: var(--muted); font-weight: 600; white-space: nowrap; }

/* --------------------------------------------------------------- hero --- */
/*
 * Paired against design-exports/raw/2 Sentinel.dc.html, SN-01. The frame is a
 * fixed 1440x920 artboard; this is the same design expressed in a way that
 * survives a 360px phone, because tests/mobile_layout.mjs measures scrollWidth
 * against the viewport on three of them and a fixed shell fails it.
 *
 * SO EVERY FIXED PIXEL IN THE FRAME BECOMES A CEILING RATHER THAN A WIDTH.
 * The headline is `clamp(2.1rem, 6.2vw, 4rem)` — 4rem IS the frame's 64px at
 * the artboard width, and it steps down rather than overflowing. The vignette
 * is `max-width: 900px`, the frame's own number, inside a percentage.
 * Letter-spacing, line-height, weight and colour are the frame's exactly:
 * those do not depend on how wide the glass is.
 */
.hero { position: relative; overflow: hidden;
        padding: clamp(2.4rem, 7vw, 5.4rem) 0 0; }

/* The frame's background: a 64px grid at 2.7% ink, and a fade to the page
   colour over the bottom half so the vignette rises out of it. */
.hero-bg { position: absolute; inset: 0; pointer-events: none;
           background-image:
             linear-gradient(rgba(236, 236, 237, 0.027) 1px, transparent 1px),
             linear-gradient(90deg, rgba(236, 236, 237, 0.027) 1px, transparent 1px),
             linear-gradient(180deg, rgba(14, 14, 15, 0) 0%,
                                     rgba(14, 14, 15, 0) 52%, var(--bg) 94%);
           background-size: 64px 64px, 64px 64px, 100% 100%; }
.hero-inner { position: relative; text-align: center;
              max-width: var(--wrap); margin: 0 auto;
              padding: 0 var(--sp-4); }

.eyebrow { font-family: var(--mono); font-size: 0.6875rem; font-weight: 500;
           letter-spacing: 0.14em; color: var(--accent);
           text-transform: uppercase; margin: 0; }
.hero h1 { font-size: clamp(2.1rem, 6.2vw, 4rem); font-weight: 600;
           letter-spacing: -0.028em; line-height: 1.06;
           max-width: 60rem; margin: 1.6rem auto 0; text-wrap: balance; }
.hero .lede { font-size: 1.03rem; line-height: 1.65; color: var(--muted);
              max-width: 42.5rem; margin: 1.5rem auto 0; text-wrap: pretty; }
.hero-cta { display: flex; justify-content: center; gap: 0.875rem;
            flex-wrap: wrap; margin-top: 2.125rem; }
.hero-cta .btn { border-radius: 8px; padding: 0.6875rem 1.375rem;
                 font-size: 0.9rem; }
.hero-law { max-width: 40rem; margin: 1.25rem auto 0; text-align: left; }
.hero-strip { font-family: var(--mono); font-size: 0.6875rem;
              letter-spacing: 0.1em; color: var(--faint);
              margin: 1.25rem 0 0; }

/* The vignette. `border-radius: 12px 12px 0 0` and no bottom border, because
   in the frame it runs off the bottom of the artboard — the card is the page
   continuing, not a box sitting on it. */
.vignette { max-width: 56.25rem; margin: 3.125rem auto 0; text-align: left;
            background: var(--surface); border: 1px solid var(--line);
            border-bottom: none; border-radius: 12px 12px 0 0;
            box-shadow: 0 30px 90px rgba(0, 0, 0, 0.5); overflow: hidden; }
.vignette-cap { font-family: var(--mono); font-size: 0.625rem;
                letter-spacing: 0.09em; color: var(--faint);
                padding: 0.5rem 1.25rem 0; }
.vig-head { display: flex; align-items: center; justify-content: space-between;
            gap: var(--sp-2); flex-wrap: wrap;
            padding: 0.6875rem 1.25rem; border-bottom: 1px solid var(--line); }
.vig-head .mono { font-size: 0.72rem; color: var(--faint); }
.pill-storm { color: var(--accent); border-color: rgba(232, 99, 90, 0.4);
              background: rgba(232, 99, 90, 0.08); }
.vig-body { padding: 1.25rem 1.5rem 1.5rem; }
.vig-title { font-size: 1.1875rem; font-weight: 600; letter-spacing: -0.01em;
             margin: 0; }
.vig-sources { font-size: 0.72rem; color: var(--faint); margin: 0.375rem 0 0; }
.vig-alerts { list-style: none; margin: 0.75rem 0 0; padding: 0;
              display: flex; flex-direction: column; gap: 0.3125rem;
              font-size: 0.72rem; color: var(--faint); }
.vig-more { color: var(--muted); }
.vig-match { background: var(--surface-2); border: 1px solid var(--line);
             border-radius: 9px; padding: 1rem 1.125rem; margin-top: 1rem; }
.vig-match-head { display: flex; align-items: center; gap: 0.75rem;
                  flex-wrap: wrap; }
.vig-sig { font-size: 0.6875rem; font-weight: 500; letter-spacing: 0.09em;
           color: var(--accent); }
.vig-terms { font-size: 0.6875rem; color: var(--faint); }
.vig-quote { background: #0B0B0C; border: 1px solid var(--line);
             border-radius: 7px; padding: 0.75rem 1rem; margin: 0.75rem 0 0; }
.vig-quote p { margin: 0; font-size: 0.9rem; line-height: 1.6; }
.vig-attr { font-size: 0.66rem; color: var(--faint); margin-top: 0.4375rem !important; }
.vig-open { margin: 0.75rem 0 0; }
.vig-link { color: var(--accent); font-size: 0.8125rem; font-weight: 500; }

.grid-3 { display: grid; gap: var(--sp-3); }
@media (min-width: 46rem) { .grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.grid-3 > * { min-width: 0; }

/* --------------------------------------------------------- the auth shell --- */
/*
 * FOUND ON THE DEPLOYED SITE in RUN-3. Sign-in and sign-up were a 26rem
 * column inside the ordinary page wrap, which means a narrow card jammed
 * against the left edge of a wide window with a field of empty space to the
 * right of it. It reads as a page that failed to load the rest of itself.
 *
 * A grid with `place-items: center` rather than `margin: 0 auto`, because the
 * card has to be centred on BOTH axes: auto margins only solve the horizontal
 * one, and a 400px form pinned to the top of a 1080px window is the same
 * lopsidedness turned ninety degrees.
 *
 * `min-height` is in `svh` with a `vh` fallback and it is 68 of them, not
 * 100. 100vh on a phone is measured against the browser chrome *retracted*,
 * so a full-height box is taller than the glass and the page scrolls when
 * nothing is off the bottom of it — and this is inside <main>, which already
 * sits under a header and above a footer, so 100 of anything would be the
 * viewport plus those two. 68 leaves the card optically centred in what is
 * left with the footer still reachable. tests/mobile_layout.mjs measures the
 * sideways overflow; this is the vertical half of the same care.
 */
.auth-shell { display: grid; place-items: center;
              min-height: 68vh; min-height: 68svh;
              padding: var(--sp-5) var(--sp-4); }
.auth-card { width: 100%; max-width: 25rem; }
.auth-card h1 { font-size: var(--step-3); margin-top: 0; text-wrap: balance; }
/* The trailing links under the form are part of the centred column, so they
   are centred with it. Left-aligned they point at nothing. */
.auth-card .auth-alt { text-align: center; margin-bottom: 0; }

.site-foot { border-top: 1px solid var(--line); margin-top: var(--sp-6);
             padding: var(--sp-4) 0; color: var(--muted);
             font-size: var(--step--1); }
.site-foot a { color: var(--muted); }
.foot-links { display: flex; flex-wrap: wrap; gap: var(--sp-3);
              margin-bottom: var(--sp-2); }

details { border: 1px solid var(--line); border-radius: var(--radius);
          background: var(--surface); padding: var(--sp-2) var(--sp-3);
          margin-bottom: var(--sp-2); }
summary { cursor: pointer; font-weight: 580; min-height: 32px;
          padding: 0.35rem 0; }
details[open] summary { margin-bottom: var(--sp-2); }

@media (prefers-reduced-motion: reduce) {
    * { animation: none !important; transition: none !important; }
}

/* The write-the-line queue. Each row is a card CONTAINING a form, so it does
 * not get the .inc-link treatment where the whole row is one link: a textarea
 * and two buttons inside a link is a row whose tap target depends on where the
 * thumb lands. The title alone is the link. */
.plain { list-style: none; margin: 0; padding: 0; }
.plain li + li { margin-top: var(--sp-1); }
a.inc-title { display: inline-block; max-width: 100%; color: inherit;
              text-decoration: none; overflow-wrap: anywhere;
              border-bottom: 1px solid var(--line); }
a.inc-title:hover { border-bottom-color: var(--accent); }

/* An FAQ question is a top-level section of the page, so it is an h2 -- the
 * page went h1 -> h3 and both Lighthouse and a screen reader read that as a
 * level gone missing. The smaller size is a style choice and does not belong
 * in the heading level. */
h2.q { font-size: var(--step-1); margin-top: var(--sp-4); }
