/* ==========================================================================
   CapInteract — reset

   Extracted from site.css, not imported from anywhere. There is no third-party
   reset here on purpose: a general-purpose one carries rules for elements this
   site never uses, and every line below exists because something in the build
   needs it.

   Loaded FIRST, before fonts.css and tokens.css. Load order does not affect the
   var() references below — custom properties resolve at computed-value time, so
   a token declared in a later sheet still reaches a rule in this one.

   What belongs here: box model, UA margin removal, and baseline behaviour that
   is true of the site regardless of which component is on screen. What does not:
   colour, type scale, and anything naming a component class. The reduced-motion
   rules for the nav stay in site.css for exactly that reason — they name
   .nav and .nav__logo-img, so they are component behaviour, not a floor.
   ========================================================================== */

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

/* Stops iOS Safari inflating type on orientation change. The only hand-written
   prefix in the codebase; §10 permits this one and no others. */
html { -webkit-text-size-adjust: 100%; }

body { margin: 0; }

/* UA margins removed.

   blockquote and figure both ship 1em 40px by default. blockquote is unused so
   far, so it is here pre-emptively. figure IS used — three components carry it —
   and each of those was zeroing the margin itself, which is three places to
   forget. One rule instead. .herodiagram__figure still sets a real margin of its
   own, which is a value rather than a patch, so that one stays in site.css. */
h1, h2, h3, p, ul, blockquote, figure { margin: 0; }

/* No list on this site wants UA markers or indentation, so the removal is
   blanket rather than opt-in.

   That has a Safari consequence, and it is why every <ul> in the markup carries
   role="list". VoiceOver drops list semantics — the "list, 5 items" announcement
   and item-by-item navigation — from any list whose list-style is none. The
   explicit role puts them back. It duplicates the element's own implicit role,
   which is precisely why it needs saying here: it reads as removable and is not.

   The rule below is not what strips the markers; the blanket rule above already
   did that for <ul>. It earns its place two ways. For <ol> it does real work,
   since nothing else here touches ordered lists. For <ul> it keeps the pairing
   legible, so scoping the blanket rule later cannot silently reintroduce markers
   on the lists that opted out. */
ul { padding: 0; list-style: none; }
ul[role="list"], ol[role="list"] { list-style: none; }

/* Form controls inherit nothing typographic in any browser — they fall back to
   the OS UI font, which would put the Let's Talk and Book a Demo fields in
   system-ui while every label around them is Inter. There is no form on the site
   yet; this is here so the first one does not have to remember. */
input, textarea, select, button { font: inherit; color: inherit; }

/* PADDING TOO, and it belongs here for the same reason the anchor rules do.
   The declaration above took font and colour and stopped, so Chrome's default
   `padding: 1px 6px` survived on every <button> — and the first control without
   a padding rule of its own inherited it silently. That was .nav__trigger: 6px
   each side made the button 12px wider than its content, put its label 6px right
   of where a sibling <a class="nav__link"> sits, and widened the visual gap
   beside "Solutions" to 38px against the row's 32px `gap`.

   Same shape as the anchor decoration reset (§5, MECHANISM FAILURE 5): a rule
   that is site-wide in intent, declared per class in practice, is a rule waiting
   for its first exception — and the exception looks like a one-off bug.

   .btn is unaffected: it sets `padding: 10px 20px` explicitly. .nav__toggle is
   unaffected in its OUTER box: it declares 44x44 and `box-sizing: border-box` is
   global, so the padding was inside the 44 and its bars are centred by
   `place-content`. */
/* AND THE BORDER, 2026-08-11 — O21. THIRD INSTANCE OF THE SHAPE DESCRIBED
   DIRECTLY ABOVE, and it was found by measuring rather than by looking.

   The paragraph above says a rule that is site-wide in intent but declared per
   class is "a rule waiting for its first exception — and the exception looks
   like a one-off bug." That is exactly what happened: `.nav__toggle` and
   `.nav__trigger` each reset their own border, `.btn` never did, and the only
   two <button class="btn"> on the site — Let's Talk and Book a Demo's Submit —
   shipped Chrome's default `2px outset rgb(0,0,0)` around a navy button.

   IT WAS INVISIBLE IN THE HEIGHT UNTIL D22. Those Submits measured 48 while
   every other .btn measured 44, and 48 was the RIGHT number, so the defect read
   as the two pages being correct. They were 24 line + 20 padding + 4 BORDER.
   Deleting this border before D22 would have silently shortened both to 44;
   since `min-height: 48px` it is height-neutral, which is why it is safe now
   and was not before.

   Figma's Button 27:195 carries no stroke on any of its 24 variants.

   The two per-class resets are now redundant. Left in place: removing them is a
   separate change with its own before/after, and they are harmless. */
button { padding: 0; border: 0; }

/* THE INPUT BOX — the third instance of this shape, and the only one that was
   PREDICTED rather than discovered. §5's reset audit named this row exactly:
   "input / textarea / select padding, border, background — nothing, no class
   exists yet. font/colour are reset, the box is not. This is the one that WILL
   bite, and it is predictable rather than hypothetical." It also said where the
   fix belongs: "in the reset rather than in a .field class".

   Today is the day the first form was built, so it lands here. Every UA gives
   these controls their own border, background and radius; the site's field
   treatment (Figma 210:219) supplies all three, and an un-neutralised default
   would show through as a doubled border or an OS-tinted box.

   `appearance` is DELIBERATELY NOT RESET HERE, and the reason CHANGED on
   2026-08-07 — read the new one before acting on the old one.

   IT USED TO BE "there is no chevron asset": stripping `appearance` from <select>
   removes the native arrow, §5 forbids inventing artwork, so the native indicator
   stayed as a recorded divergence (D10). THAT IS NO LONGER TRUE. The chevron was
   exported from the Figma Select component and ships as
   `img/icons/icon-chevron-down.svg`, D10 is closed, and `site.css` now sets
   `appearance: none` on `select.field__input`.

   IT STAYS OUT OF THIS GLOBAL ROW ANYWAY, for a narrower reason: `appearance:
   none` on a bare `select` selector would strip the indicator from any future
   select that has no replacement drawn for it, and a dropdown with no arrow does
   not read as a dropdown. The override belongs with the treatment that supplies
   the replacement, which is the `.field__input` block. */
input, textarea, select { background: none; border: 0; border-radius: 0; }

/* <cite> is italic in every UA, and this site loads NO italic file - §10 records
   two variable fonts, weight axis only. An italic <cite> would therefore be
   SYNTHESISED by the browser, which is a sheared upright rather than a designed
   face. Reset here rather than on .notfound__quote-cite for the reason the anchor
   and button rules are here: the site uses <cite>, and the next one should not
   have to remember. */
cite { font-style: normal; }

/* display:block kills the inline-descender gap under every image. max-width
   with height:auto keeps an image inside its column without distorting it —
   though note that a diagram which must FILL its column needs width:100% as
   well, since max-width cannot scale an image up. See CLAUDE.md §5. */
img, svg { display: block; max-width: 100%; height: auto; }

/* Anchor decoration belongs HERE, once, not on every link class.
   This file already neutralised anchor COLOUR and stopped at decoration, so a bare
   <a> kept the browser's underline and each link class had to declare
   text-decoration: none for itself. Three did — .btn, .nav__link/.nav__sublink and
   .footer__link — and every link on the site looked right only because it happened
   to carry one of them. The first anchor that did not, a.footer__legal, arrived
   underlined at rest.
   A site-wide rule enforced per-class is a rule waiting for its first exception.
   See CLAUDE.md §5, mechanism failure 5. */
a { color: inherit; text-decoration: none; }

/* Baseline focus indicator, for every focusable element rather than buttons
   alone. Only paints while an element has focus, so it changes nothing about the
   page at rest.

   TWO TONES, AND IT HAS TO STAY THAT WAY. Do not simplify this to one colour.

   The site puts focusable elements on four different surfaces, and NO single
   colour clears the 3:1 that WCAG 2.2 SC 1.4.11 asks of a focus indicator on
   all four. Measured:

                      default  sunken   brand    teal CTA
     brand-accent       2.37 x   2.24 x   6.37     1.00 x
     text-accent        7.46     7.06     2.02 x   3.15
     white              1.00 x   1.06 x  15.06     2.37 x
     text-primary      17.36    16.44     1.15 x   7.34

   Every row has at least one failure. The previous single teal ring failed on
   three of the four.

   So the ring is white inside, navy outside, and one tone always carries it:

     on surface/default   navy   17.36  PASS
     on surface/sunken    navy   16.44  PASS
     on surface/brand     white  15.06  PASS
     on the teal CTA band navy    7.34  PASS

   The white and navy bands are 17.36:1 against EACH OTHER, which is what makes
   this robust rather than merely arithmetically true: on the navy hero the outer
   navy band reads as background, but the white band is still framed against it,
   so the indicator stays perceivable rather than melting into the section.

   Mechanics: the box-shadow spread paints 0-4px outside the border box and the
   outline paints 0-2px outside it. Outlines paint on top of shadows, so the
   result is 2px white then 2px navy. Nothing in the codebase clips it -- the
   only overflow:hidden is inside .u-sr-only, which is a CHILD of links and
   never an ancestor of anything focusable. If that ever changes, swap the
   box-shadow for a second outline plus outline-offset. */
:focus-visible {
  outline: 2px solid var(--surface-default);
  outline-offset: 0;
  box-shadow: 0 0 0 4px var(--text-primary);
}

/* Motion floor. Anything the site animates stops animating when the user has
   asked for that, without each component having to remember. Components may
   still need their own rules on top — the nav has to restore a static
   background because its theme swap is carried by a transition. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
