/* =============================================================================
   PRISM II - FORMS, and the two public surfaces they exist for.

   THIS SITE HAD NO INPUT STYLING AT ALL until 2026-09-03, and /audit's own
   header comment said why: "there is no form on this site by design, so the
   audit is requested by mail with the subject already written." The audit
   request form is what changed that. /contact joined it on 2026-09-04, and
   THAT IS WHY THIS FILE IS NOT site_07_audit: everything from THE FIELDS
   downward was already generic and is now shared verbatim by both, and a
   second file would have meant a second copy of the field vocabulary drifting
   one input at a time. The two page-level blocks are scoped (.ar-, .ct-) and
   share their declarations wherever the two surfaces genuinely agree.
   The admin area has its own vocabulary (.gtm-form, in application.css) which
   this deliberately does not reach for: that file loads AFTER every site_* one,
   so borrowing from it would mean a public page whose fields are styled by a
   sheet the public pages have no other relationship with.

   WHERE THIS SITS IN THE CASCADE: site_07 is the eighth numbered file and loads
   last of the site_* set, which is where a surface that reuses tokens from
   site_00 and shapes from site_04 belongs. test/assets/site_stylesheets_test
   pins the ordinal run, so renaming this reorders the cascade.

   THE FOUR RULES THIS FILE IS BOUND BY, each with a test behind it:

     A LIGHT HUE NEVER CARRIES TYPE. --ember, --peri, --cobalt, --apricot,
     --lilac, --ice and --rose may border, wash or stroke. Every `color` here
     takes an ink token or a text partner, and colour_vocabulary_test globs
     site_* so this file is checked automatically.

     ROUNDED IS RESERVED FOR ACTIONS. The submit is a pill because every CTA on
     this site is. Every field is square with a hairline, because a rounded input
     would make the form read as a widget dropped onto the page rather than part
     of it.

     12px IS THE FLOOR, and the inputs sit far above it: 16px, which is also the
     size below which iOS zooms the viewport on focus and leaves a visitor
     scrolled sideways mid-form.

     44px MINIMUM ON ANYTHING PRESSED, including every field, not just the
     button. A select is a touch target too.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   THE REQUEST SURFACE. Form on the left, page one of the report on the right.

   THREE BANDS, NOT TWO TRACKS (2026-09-03). This was a two-column grid holding
   the pitch and form on the left and page one of the report on the right. Three
   blocks of very different lengths in two tracks is what produced 380px of dead
   space under the submit button: the track carrying two of them ran away from
   the other. A mechanical layout scan came back clean, which was the tell that
   the topology was the fault rather than the spacing.

   The pitch is now its own full-width band, which is what fixes the arithmetic:
   sitting above the form it put 290px on the left track before a single field
   was drawn. The deck is the two-up beneath it, and the manifest closes the band
   full width.
   -------------------------------------------------------------------------- */
.ar { padding: 42px 0 84px; }

/* THE BARE `section { border-top }` IN application.css, NEUTRALISED.
   That file styles every <section> element in the app, /labs and /admin
   included, and it loads in the same bundle as this one. Both of these are
   <section> elements sitting directly under the header, so they inherited a
   hairline that rendered as a stray rule across the top of the page, at the
   content measure rather than the full width, above the eyebrow. Nothing
   raised; it simply looked like a design decision nobody made.

   A class beats an element selector on specificity, so this holds whichever
   way round the two files end up sorting in Propshaft's cascade. */
.ar,
.ct,
.ar-note { border-top: 0; }

/* THE PITCH. Full width, so its measures are the page's rather than a column's:
   the headline was capped at 16ch and the lede at 46ch, both sized for half a
   page, and at 56px that set the headline to about four words a line. */
.ar-pitch,
.ct-pitch {
  border-bottom: 1px solid var(--line);
  padding-bottom: 30px;
  margin-bottom: 36px;
}
.ar-eyebrow,
.ct-eyebrow { line-height: 1.4; margin-bottom: 24px; }
.ar-pitch h1,
.ct-pitch h1 { max-width: 22ch; text-wrap: balance; }
.ar-lede,
.ct-lede { margin: 24px 0 0; max-width: 62ch; }

/* The way back into the argument, and it is sized to lose to the form. One step
   under the lede at 15px against its 19, in --ink2 rather than --ink, so it reads
   as an aside rather than a second offer. The page's one-ask rule is about
   buttons; this is a text link and must never grow into anything that competes
   with the submit. */
.ar-back { margin: 14px 0 0; font-size: 15px; color: var(--ink2); max-width: none; }
.ar-back a { color: var(--accent, var(--deep)); }

/* THE DECK, AND THE TRACKS ARE DELIBERATELY UNEVEN. 46/54 rather than 1fr 1fr,
   which lands the form at 469px and the plate at 551px on the 1140px measure.

   The reason is MEASURE, not height. Even columns were right while the right pane
   was the only thing in it: page one of the report is a reproduction carrying the
   renderer's own full-width mono lines, and a narrow track wraps its eyebrow and
   its scores label mid-phrase. A form wants the opposite. Both panes now get the
   width they want.

   Do not expect the ratio to balance the two heights, which is what it was first
   reached for. Measured live at 40/60, 46/54, 52/48 and 58/42, the form's height
   did not move by a pixel and the cover only began to grow once its track dropped
   under 490px, narrower than the reproduction can take. What levels them is the
   one paired row in the form: 826px against 826px, measured.

   STRETCHED, WITH THE SUBMIT ANCHORED TO THE FOOT OF ITS COLUMN. The tracks are
   equal height and the form's own content is shorter than the report, so the
   remaining space falls between the last field and the button rather than below
   the button. Two things come out of that: the columns are level at any content
   length, and the button's bottom edge lands on the report's caption, which is
   the horizontal the deck is read against.

   It also stops the balance being a coincidence of how many fields the form has.
   The form was level at 826px with a company size field; that field was removed
   the same day and the form dropped to 732, putting a 94px hole back under the
   button. Anchoring the action absorbs a field being added or removed without
   anyone having to re-measure.

   Nothing stretches inside the artefact column: the cover is a block, so an
   equal-height wrapper leaves the reproduction exactly the size it was. Scaling
   it would make it a different document from the one /ai-visibility shows.

   NO STICKY, AND NO EYEBROW OFFSET. The artefact used to be pinned and pushed
   down by an --ar-eyebrow-h token so its top edge met the headline rather than
   the eyebrow. With the pitch lifted out, the two columns start level on their
   own and end level too, so both are solving a problem that no longer exists. */
.ar-deck {
  display: grid;
  grid-template-columns: 46fr 54fr;
  gap: 56px;
}
.ar-deck > div { min-width: 0; display: flex; flex-direction: column; }

/* THE MANIFEST CLOSES THE BAND. Two columns, because seven rows down one side of
   a full-width band is a very long thin list and the descriptions are what make
   the pages sound worth having.

   .report-contents is styled in site_04_offers and shared with /ai-visibility,
   so everything here is scoped to this page and changes nothing there. The
   last-child rule is restored deliberately: site_04 strips the final row's
   border because in one column it closes the list, and in two columns that
   leaves one column ending on a rule and the other not. */
.ar-spread { margin-top: 44px; }
.ar-spread .report-contents ol { columns: 2; column-gap: 52px; }
.ar-spread .report-contents li { break-inside: avoid; }
.ar-spread .report-contents li:last-child { border-bottom: 1px solid var(--line); }

/* -----------------------------------------------------------------------------
   THE CONTACT SURFACE (2026-09-04). Form on the left, the other two asks on the
   right.

   THE DECK IS 56/44, WHICH IS .ar-deck's RATIO REVERSED, and that is a decision
   rather than a copy error. Both ratios are MEASURE decisions and neither is a
   height one. On /audit the wide pane is a reproduction of the report cover,
   carrying the renderer's own full-width mono lines, and a narrow track wraps
   its eyebrow and its scores label mid-phrase - so the form takes the narrow
   side there. Here the wide pane IS the form, eight fields deep, and the narrow
   one is a three-row list whose longest line is a sentence. Both panes get the
   width they want, and on this page that points the other way.

   STRETCHED, WITH THE SUBMIT ANCHORED TO THE FOOT OF ITS COLUMN, exactly as
   .ar-deck is: .form-close's `margin-top: auto` puts the remaining space between
   the last field and the button rather than below the button, so the two columns
   are level at any content length and adding or removing a field never reopens a
   hole. Do not reach for align-items here - the levelling is the form's job.
   -------------------------------------------------------------------------- */
.ct { padding: 42px 0 84px; }

.ct-deck {
  display: grid;
  grid-template-columns: 56fr 44fr;
  gap: 56px;
}
.ct-deck > div { min-width: 0; display: flex; flex-direction: column; }

/* THE ALTERNATIVES. A hairline list, which is the vocabulary this site already
   uses for "a short run of things you might pick" - .report-contents, the labs
   index, .ar-checks. Not cards: a card would make each row an object competing
   with the form, and the whole argument of the page is that these are exits from
   it rather than rivals to it. */
/* STICKY, WHICH .ar-deck's ARTEFACT DELIBERATELY IS NOT, and the difference is
   measured rather than stylistic. On /audit the two columns start level and end
   level, so pinning one solved a problem that did not exist and was deleted.
   Here they cannot: the form is eight fields deep and this is a three-row list,
   measured at 1,125px against 494px, leaving 631px of empty column beside the
   message field and the submit button. That is more dead space than the 380px
   that forced /audit's own rebuild.

   Pinning is the right fix rather than padding it out, because the space is not
   the only problem. Scrolled to the message field, the alternatives have left
   the screen entirely — so the reader most likely to want one, the one who has
   reached the big empty box and paused, is the one who cannot see them.

   `top` clears the sticky header (68px) plus a gap. It goes STATIC below 980px,
   where the deck is one column and there is no second track to stay beside. */
.alts {
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 92px;
}
/* SET AS THE SENTENCE IT IS, NOT AS A LABEL (2026-09-04). This line carries the
   whole argument of the page — that Contact does not compete with the audit and
   the booking, it contains them — and it was 12px uppercase mono in --ink3,
   beside a 56px headline. The smallest, faintest voice in the design system,
   making the largest claim on the surface. Both halves of the critique landed on
   it independently: to a first-time visitor the page read as a form with a
   sidebar rather than as three ranked routes.

   Uppercase mono is this system's LABEL voice, for things short enough to be
   labels. Seven words addressed directly at a reader is not a label, it is a
   sentence, so it takes the sans face at body size in sentence case. The row
   CTAs below stay mono, which is what keeps the block feeling like part of the
   same vocabulary. Costs no layout. */
.alts-head {
  margin: 0;
  padding-bottom: 18px;
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.4;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink2);
}
.alt {
  padding: 20px 0;
  border-bottom: 1px solid var(--line);
}
/* The rule above the first row closes the list at the top, the same way
   .ar-checks' border-top does. Without it the heading floats over an open list. */
.alt:first-of-type { border-top: 1px solid var(--line); }
/* 17px, NOT 18. The ladder is 96/56/38/28/21/19/17/16/15/13/12 and 18 is not on
   it; nobody would see the difference and the point is that the ladder does not
   drift one authored value at a time, which is exactly how labs_07 ended up with
   sixteen sizes in one file. */
.alt .nm {
  margin: 0 0 6px;
  font-family: var(--display);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -.012em;
  color: var(--ink);
}
.alt .bl { margin: 0 0 12px; font-size: 15px; color: var(--ink2); }

/* --accent is --clay on p-contact, a TEXT PARTNER rather than a light hue, which
   is what keeps this legal under the rule colour_vocabulary_test enforces across
   every site_* file. */
/* 44px, WHICH THESE MISSED BY MORE THAN HALF (2026-09-04). Measured at 19.2px
   for both CTA rows and 22.4px for the address — under WCAG 2.5.8's 24px floor
   and nowhere near this system's own unconditional 44px on anything pressed.
   The comment above still stands: these must not become pills, or they outrank
   the submit button beside them. A target is a hit area, not a shape, so the
   height comes from padding and the link still reads as a link.

   `align-self: flex-start` keeps the padded box from stretching to the column
   width, so the hit area matches what the eye reads as the control. */
.alt .go {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  min-height: 44px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--accent, var(--clay));
}
.alt .go::after { content: " \2192"; margin-left: 7px; }
/* The email address is the control, so it is set as itself rather than as a
   label: uppercasing an address makes it harder to read and to copy, and an
   arrow after it would claim it goes somewhere on this site. */
.alt .go.is-plain {
  font-size: 15px;
  letter-spacing: 0;
  text-transform: none;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.alt .go.is-plain::after { content: none; }
.alt .go:hover { color: var(--ink); }

.alt-foot { margin: 18px 0 0; color: var(--ink3); }

/* The list style for the three pages the request flow passes through: check your
   email, confirmed, and the link that did not resolve. It was the audit page's
   four-item checks list first; that list is gone and the manifest carries the
   deliverable now, but these three pages still each have a short run of facts to
   set, and a mono-labelled hairline list is what the band already uses. */
.ar-checks {
  list-style: none;
  padding: 0;
  margin: 36px 0 0;
  border-top: 1px solid var(--line);
}
.ar-checks li {
  position: relative;
  padding: 14px 0 14px 26px;
  border-bottom: 1px solid var(--line);
  font-size: 15px;
  color: var(--ink2);
}
.ar-checks li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 21px;
  width: 10px;
  height: 1px;
  background: var(--accent, var(--cobalt));
}

/* The three pages the flow passes through after the form: check your email,
   confirmed, and the link that did not resolve. One column, measured, with the
   same top padding the request surface opens on so the three read as one place. */
/* The onward block on /audit/confirmed. It shares .ar-note's measure so the two
   read as one column, and takes a hairline above rather than a panel or a fill:
   it is a coda to the page, not a second offer competing with the first. The
   note above it loses its bottom padding when this follows, or the rule sits in
   96px of nothing. */
.ar-after {
  border-top: 1px solid var(--line);
  max-width: 62ch;
  padding: 32px 0 96px;
}
.ar-after .body { margin: 12px 0 0; max-width: 58ch; }
.ar-after .btn.plain { margin-top: 16px; }
.ar-note:has(+ .ar-after) { padding-bottom: 42px; }

.ar-note { padding: 42px 0 96px; max-width: 62ch; }
.ar-note h1 { max-width: 18ch; text-wrap: balance; }
.ar-note .lede { margin: 24px 0 0; }
.ar-note .btns { margin-top: 32px; }
.ar-note .small { margin-top: 28px; }

/* /contact/sent IS THE ONE .ar-note WHOSE ASIDE IS A SINGLE LINE, AND TWO
   SEPARATE CAPS HAD TO MOVE FOR IT (2026-09-04).

   The sender address reads as one clause and should set as one line. It was
   wrapping at 590px inside a 662px section, which looks like a measure error
   rather than a measure: site_00's global `p { max-width: 64ch }` is right for
   prose but resolves against the ELEMENT's own size, so 64ch of 15px .small is
   72px narrower than 62ch of the 19px lede above it. `max-width: none` hands the
   aside the section's measure, which is the cap that was meant to hold it.

   That alone lands the line at 660px against a 661.8px section — under 2px of
   slack, so any platform's font rendering wraps it back. 68ch is the same
   decision as the header's 12px of slack at 960: the measured minimum plus room
   for a machine that is not this one. The lede stays at two lines to past
   1020px, so widening costs the paragraph above nothing.

   Scoped to .p-contact because /audit/sent, /audit/confirmed and
   /verify_failed share this class and their asides are genuinely paragraphs. */
.p-contact .ar-note { max-width: 68ch; }
.p-contact .ar-note .small { max-width: none; }

/* -----------------------------------------------------------------------------
   THE FLASH, which the public layout could not render until 2026-09-04.

   It borrows .form-errors' vocabulary deliberately — a hairline in the status
   hue over a 7% wash of it — because a visitor meeting this has almost certainly
   just pressed submit on a form whose validation summary looks exactly like it.
   One answer to "something went wrong", not one per surface.

   --miss and --pass are STATUS tokens rather than spectrum ones, which is what
   makes them legal to carry type here, and the message always says what happened
   in words: the colour is never the only signal.
   -------------------------------------------------------------------------- */
.site-flash {
  margin: 20px 0 0;
  padding: 14px 18px;
  font-size: 15px;
  line-height: 1.5;
}
.site-flash.is-alert {
  border: 1px solid var(--miss-line);
  background: color-mix(in srgb, var(--miss) 7%, var(--bg));
  color: var(--ink);
}
.site-flash.is-notice {
  border: 1px solid var(--pass-line);
  background: color-mix(in srgb, var(--pass) 7%, var(--bg));
  color: var(--ink);
}

/* -----------------------------------------------------------------------------
   THE FIELDS
   -------------------------------------------------------------------------- */
.form-field { margin-bottom: 18px; }

/* ONE COLUMN IN TWO GROUPS, WITH ONE PAIRED ROW. The fields used to run in two
   paired rows, and .form carried a 520px cap. The cap is gone, because the 469px
   track governs the measure now, and job title and company size unstacked.

   First and last name stay paired: they are one fact split across two inputs, and
   the pair is what actually levels the two columns. Nothing about the track widths
   could do that, measured live at four ratios from 40/60 to 58/42 — the form's
   height never moved at all and the cover only began to grow once its track
   dropped below 490px, which is narrower than the reproduction can take.

   A fieldset needs three resets and a fourth that is not obvious: min-width: 0.
   The UA stylesheet gives every fieldset `min-width: min-content`, which makes
   it refuse to shrink below its widest child and quietly blows out any grid or
   flex track it sits in. */
.form-group {
  border: 0;
  margin: 0 0 26px;
  padding: 0;
  min-width: 0;
}
.form-group + .form-group {
  border-top: 1px solid var(--line);
  padding-top: 24px;
}

/* --accent is --deep on p-audit, a TEXT PARTNER rather than a light hue, so this
   satisfies the rule colour_vocabulary_test enforces across every site_* file:
   ember, peri and cobalt may wash, stroke or border, and never carry type. */
/* The one paired row, collapsing below 620px. Pairs are for fields answered
   together; a required field is never paired with an optional one. */
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.form-row .form-field { margin-bottom: 18px; }

/* THE LEGEND CARRIES THE HIERARCHY, NOT THE FIELDS (2026-09-03).

   A critique found the form's visual system contradicting its own argument: the
   first legend says two of these fields are what the audit cannot run without,
   and then all six inputs render identically, so the claim is made in words and
   refuted in pixels one row later.

   THE FIX IS NOT TO RANK THE INPUTS. Making the two required fields heavier is
   the obvious move and it is wrong twice over — it contradicts an explicit
   decision recorded in the form partial ("every field the same size so none of
   them looks more important than it is"), and a coloured stroke down the side of
   a control is the decoration this design system does not use. Five of the six
   fields are required anyway; the distinction the legends draw is between what
   the audit NEEDS and what the reply needs, which is a fact about the groups.

   So the group label gets the weight instead: a short accent rule before it, the
   same 10px mark .ar-checks already draws on the three pages this flow passes
   through, so the emphasis arrives in vocabulary the visitor has met. --accent is
   --deep on p-audit, a text partner rather than a light hue, which is what keeps
   this legal under the rule colour_vocabulary_test enforces. */
.form-group-label {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0;
  margin-bottom: 18px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--accent, var(--deep));
}
.form-group-label::before {
  content: "";
  flex: 0 0 auto;
  width: 10px;
  height: 1px;
  background: currentColor;
}

.form-label {
  display: block;
  margin-bottom: 8px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink3);
}
/* "Optional" is said in the label rather than implied by the absence of an
   asterisk on the two required ones. A visitor scanning for the shortest path
   through a form should be able to find it without pressing anything. */
/* NO opacity (2026-09-04). --ink3 measures 6.53:1 on white, comfortably past AA
   — and `opacity: .75` composited that down to 3.65:1, under the 4.5 required at
   12px. The token was never the problem; the transparency on top of it was, and
   it is the kind of failure that survives review because it passes in dark mode
   (4.88:1) and looks like a deliberate softening in light.

   The word still reads as subordinate without it: it is lowercase beside an
   uppercase label, at the same size, which is a difference in voice rather than
   in strength. /audit shows this once and /contact three times, so both surfaces
   gain from the fix. */
.form-optional {
  margin-left: 6px;
  letter-spacing: .04em;
  text-transform: none;
  color: var(--ink3);
}

/* THE FIELD BORDER IS ITS OWN TOKEN, AND --line2 WAS FAILING WCAG 1.4.11.

   Measured on the rendered page: 1.68:1 in light and 2.17:1 in dark, against the
   3:1 that non-text UI component boundaries require. On a page that is entirely
   form, the boundary IS the affordance — there is no other cue that a field is a
   field — so this is the one element on /audit that has to clear that bar, and
   it was the only one below it.

   Not a change to --line2 itself, which is right where it is: it draws hairlines
   between rows and around cards all over this site, where the rule that applies
   is the decorative one rather than 1.4.11. A field is a control. It gets its
   own value, computed to land just past 3:1 on each ground rather than as far
   from it as a heavier stroke would go: an input that outlines itself harder
   than the type inside it reads as a widget, which is the thing the square-field
   decision above exists to avoid.

   Declared three times for the same reason every token on this site is — once
   plain, once behind the system preference guarded so an explicit light choice
   still wins, once behind an explicit dark choice. */
:root { --field-line: rgba(28,23,15,.50); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --field-line: rgba(242,239,233,.40); }
}
:root[data-theme="dark"] { --field-line: rgba(242,239,233,.40); }

.form-input,
.form-select,
.form-textarea {
  display: block;
  width: 100%;
  min-height: 48px;
  padding: 12px 14px;
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.4;
  color: var(--ink);
  background: var(--bg);
  border: 1px solid var(--field-line);
  border-radius: 0;
  appearance: none;
}

/* A MARKED FIELD, AND THE COLOUR IS NEVER THE ONLY MARK. --miss is a status
   token rather than a spectrum one, and it arrives here with an inline message
   under the input and aria-invalid on it, so a reader who cannot see the border
   at all gets the same information in the same place. */
/* THE TEXTAREA IS AN INPUT WITH A DIFFERENT HEIGHT, and nothing else. It takes
   the same hairline, the same square corners and the same 16px - which is also
   the size below which iOS zooms the viewport on focus and leaves a visitor
   scrolled sideways mid-form.

   `resize: vertical`, not `none` and not `both`. None takes away the one control
   a person writing more than three lines actually wants; both lets them drag the
   field wider than the column and break the deck. Vertical is the only axis that
   cannot damage the layout. */
.form-textarea { min-height: 132px; resize: vertical; }

.form-input[aria-invalid="true"],
.form-textarea[aria-invalid="true"] { border-color: var(--miss); }
.form-input::placeholder,
.form-textarea::placeholder { color: var(--ink3); opacity: 1; }

.form-input:hover,
.form-select:hover,
.form-textarea:hover { border-color: var(--ink3); }

/* The same focus treatment the .ask pill takes in site_06, so the site has one
   answer to "where am I" rather than one per component. */
.form-input:focus-visible,
.form-select:focus-visible,
.form-textarea:focus-visible,
.form-submit:focus-visible {
  outline: 2px solid var(--fill-primary);
  outline-offset: 2px;
}

/* The chevron is drawn rather than left to the platform, because appearance:none
   removes the native one and a select with no affordance reads as a dead text
   field. --draw is a stroke token, so this is not a light hue carrying type. */
.form-select {
  padding-right: 40px;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--ink3) 50%),
    linear-gradient(135deg, var(--ink3) 50%, transparent 50%);
  background-position: right 20px center, right 14px center;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}

.form-hint {
  margin: 7px 0 0;
  font-size: 13px;
  line-height: 1.45;
  color: var(--ink3);
}

/* THE INLINE MESSAGE, DIRECTLY UNDER THE FIELD IT BELONGS TO. The form had a
   summary at the top and nothing beside the field, so a reader sent back to fix
   one input had to carry "which one was Email" 300px down the page themselves.
   It sits ABOVE the hint, which is the order aria-describedby announces them in:
   what went wrong, then what the field wants. --miss carries the type here and
   is a status token, which is what makes that legal under the light-hue rule. */
.form-error {
  margin: 7px 0 0;
  font-size: 13px;
  line-height: 1.45;
  font-weight: 500;
  color: var(--miss);
}

/* THE WARNING IS NOT AN ERROR AND MUST NOT LOOK LIKE ONE. It fires on blur, from
   the email-domain controller, before anything has been submitted or refused —
   so it takes --part, the status token for a partial result, rather than --miss.
   Nothing has failed yet; something is about to. */
.form-warning {
  margin: 7px 0 0;
  font-size: 13px;
  line-height: 1.45;
  color: var(--part);
}

/* Errors use --miss, which is a STATUS token rather than a spectrum one, and it
   never appears without the words that say what is wrong. */
.form-errors {
  margin-bottom: 24px;
  padding: 16px 18px;
  border: 1px solid var(--miss-line);
  background: color-mix(in srgb, var(--miss) 7%, var(--bg));
}
.form-errors .mono { margin: 0 0 8px; color: var(--miss); }
.form-errors ul { margin: 0; padding-left: 18px; }
.form-errors li { font-size: 15px; color: var(--ink); }
.form-errors li + li { margin-top: 4px; }
/* Each message is an in-page link to the field it belongs to. Underlined rather
   than coloured, because the panel already carries a status hue and a second one
   inside it would make the two compete for the same meaning. */
.form-errors a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.form-errors a:hover { color: var(--miss); }

.form { display: flex; flex-direction: column; flex: 1 1 auto; }

/* THE CLOSE: THE ASSURANCE AND THE ACTION, AS ONE BLOCK.

   `auto`, not a fixed value: this is what pushes the action to the foot of its
   column so it lands on the report's caption. See the note on .ar-deck.

   IT MOVED FROM .form-submit TO THIS WRAPPER ON 2026-09-03, and the reason is
   what the space was doing. Measured, the auto margin opened 148px between the
   last field and the button, and a critique put it plainly: dead space ABOVE a
   CTA detaches it from the form it belongs to, while dead space below it does
   not. The mechanism is still needed, so the fix is not to remove the space but
   to give it something to hold. The assurance copy now sits in it, the button
   stays anchored to the foot of the column, and the columns stay level. */
.form-close { margin-top: auto; }

/* Reads at the size of a hint because it IS one, and sits close enough to the
   button to be read as part of the same decision. --ink2 rather than --ink3:
   this is the last thing somebody reads before committing, not a footnote. */
/* NO max-width. It carried 46ch, which is a measure for prose sitting in an open
   column; here the column is already 469px and the field it belongs to spans all
   of it, so the cap only wrapped the last two words onto a line of their own. The
   hints above it are uncapped for the same reason: the field IS the measure. */
.form-assurance {
  margin: 22px 0 14px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink2);
}

/* BELOW THE BUTTON, which /contact can afford and /audit cannot. The auto margin
   above only opens a gap when the form is the SHORTER column, which is true on
   /audit (the report cover is taller) and false here (the form is). With no gap
   to fill, the copy is free to sit under the action — and 14px under it rather
   than 22px over it, because it is now read after the decision rather than as
   the last thing before it. */
.form-assurance.is-below { margin: 14px 0 0; }

/* No padding-top. It was 10px, which is PADDING on an input[type=submit] and
   therefore set the label 10px below the centre of a 52px button. The narrow
   breakpoint already reset it to 0, which is why the two never looked alike. */
.form-submit {
  width: 100%;
  min-height: 52px;
  font-family: var(--sans);
  cursor: pointer;
}

/* THE HONEYPOT. Positioned off-screen rather than display:none or
   visibility:hidden, both of which a bot can cheaply detect and skip. The field
   is also out of the tab order and out of the accessibility tree in the markup,
   so nothing but a script that fills every input it finds ever lands in it. */
.form-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* -----------------------------------------------------------------------------
   NARROW. The artefact goes BELOW the form rather than above it: on a phone the
   thing to reach first is the first field, and a full-width reproduction of a
   report cover ahead of it is a scroll before the page's only job starts.
   -------------------------------------------------------------------------- */
@media (max-width: 980px) {
  .ar { padding-bottom: 64px; }
  .ar-deck { grid-template-columns: 1fr; gap: 48px; }
  /* Same call on /contact, and for the same reason in reverse: stacked, the
     thing to reach first is the first field, and three exits from a form ahead
     of the form itself is an invitation to leave before reading it. */
  .ct { padding-bottom: 64px; }
  .ct-deck { grid-template-columns: 1fr; gap: 48px; }
  /* No second track to stay beside, and a pinned block in a single column
     follows the reader down the page over the content below it. */
  .alts { position: static; }
  /* Stacked, there is no second column to level against, so the auto margin
     would open a hole under the last field rather than close one. The assurance
     copy still sits above the button; it is the one thing in that gap that
     earns its place at every width. */
  .form-close { margin-top: 4px; }
  /* One column of seven rows is the right shape at this width; two would give
     each description about 30 characters a line. */
  .ar-spread .report-contents ol { columns: 1; }
}

/* -----------------------------------------------------------------------------
   PHONE. THE PITCH IS COMPRESSED HERE BECAUSE THE FOLD MOVED (2026-09-03).

   The hero band was deleted from this page for one measured reason: 656px of
   gradient before the first field put every input below the fold on a laptop, so
   the page's whole job happened after a scroll. That was measured on a laptop and
   never on a phone, where the same problem reassembled itself out of different
   parts. At 390x844: the pitch ran 424px, the lede alone was 206px over seven
   lines, and the first input's top edge sat at y=621 — with browser chrome, a
   visitor saw the top edge of one field and nothing else. Cold-email traffic
   skews mobile, so that is the majority case, not the edge one.

   NOTHING IS HIDDEN. Every word of the pitch is still on the page at every width;
   what changes is how much room it takes to say it. Four compressions, in order
   of what they returned:

     THE HEADLINE'S MEASURE CAP GOES. 22ch is right on a full-width band at 56px;
     at 390px the type is already down to 30px and the cap was then setting it to
     about 22 characters inside a 342px column, adding a line for nothing.

     THE LEDE DROPS TO BODY SIZE. 19px is a lede on a page with a hero above it.
     Under a headline that is itself down to 30px, 17px is the correct step and
     saves a line and a half.

     THE EYEBROW AND THE RULE TIGHTEN. 24px under a one-line label and 26/30 either
     side of a hairline are desktop rhythm read at half the width.

   Together these put the first field's label above the fold with its hint and the
   second field's label visible under it, which is the bar: a visitor who never
   scrolls should still be able to see that this is a short form about two things.
   -------------------------------------------------------------------------- */
@media (max-width: 620px) {
  .ar,
  .ct { padding-top: 26px; }
  .form-row { grid-template-columns: 1fr; gap: 0; }
  .ar-pitch,
  .ct-pitch { padding-bottom: 20px; margin-bottom: 22px; }
  .ar-eyebrow,
  .ct-eyebrow { margin-bottom: 16px; }
  .ar-pitch h1,
  .ct-pitch h1 { max-width: none; }
  .ar-lede,
  .ct-lede { margin-top: 18px; font-size: 17px; }
  .form-group-label { margin-bottom: 14px; }
  .ar-note { padding: 32px 0 72px; }
}
