/*
 * Shared interaction + mark layer for every safebind.ai static page.
 *
 * Exists because the per-page copies drifted exactly the way copies do: the hover block was
 * pasted into ten inline <style>s, and the one page with a JS-disabled submit button
 * (trustedform-alternative) was the one whose copy lacked the :not(:disabled) guard — so a dead
 * button lifted under the cursor as though clickable. Behaviour lives HERE, once; each page keeps
 * only its own SIZING and skin (padding, font-size, colours), which genuinely differ by page
 * family.
 *
 * Load order contract: this file is linked BEFORE each page's inline <style>, so a page rule of
 * equal specificity can always override a shared one by simply existing.
 */

/* ---- Buttons: hover / focus / press behaviour (never sizing, never skin) ---- */

.btn {
  transition:
    transform 0.12s ease,
    box-shadow 0.12s ease,
    background-color 0.12s ease,
    border-color 0.12s ease,
    filter 0.12s ease;
}
/* :not(:disabled) on EVERY dynamic rule — a dead button that lifts under the cursor reads as
   clickable. A control inside a disabled <fieldset> matches :disabled too, so form pages are
   covered without their own guard. Anchors never match :disabled and are unaffected. */
.btn:not(:disabled):hover { transform: translateY(-1px); }
.btn.primary:not(:disabled):hover { filter: brightness(1.06); box-shadow: 0 16px 40px -6px rgba(79, 140, 255, 0.62); }
.btn:not(.primary):not(:disabled):hover { border-color: var(--accent); background: rgba(79, 140, 255, 0.1); }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
/* Declared AFTER :hover — equal specificity, so the press only wins by coming later. */
.btn:not(:disabled):active { transform: translateY(1px); }
@media (prefers-reduced-motion: reduce) {
  .btn { transition: none; }
  .btn:hover, .btn:active { transform: none; }
}

/* ---- Marks: the drawn tick / cross / dash (geometry lives in /icons.svg) ---- */

/* Skin only — width/height/alignment belong to each call site, which genuinely differ.
   currentColor keeps every mark tied to the colour its container already set. */
.mark {
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ---- Mobile nav: the hamburger that stands in for the hidden desktop links (≤900px) ----
   The collapse breakpoint lives HERE, once — the per-page copies had already drifted
   (680/720/760px) before it was centralized.

   900, not 760: at 768px (iPad portrait) the full link row plus the brand and the account pills
   needs ~892px, so eleven pages scrolled sideways — measured 2026-09-04, and true before the
   Sign up pill existed ("Log in" alone ended at 812px). The menu now takes over wherever the row
   does not fit. */

/* Desktop: the wrapper must be invisible to layout — the links stay direct flex items of <nav>,
   so the nav's own gap/alignment keep working exactly as before the wrapper existed. */
.navlinks { display: contents; }
.menu-btn { display: none; }

@media (max-width: 900px) {
  header { position: relative; }
  .menu-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    padding: 0;
    border: 1px solid var(--line2);
    border-radius: 9px;
    background: transparent;
    color: var(--ink);
    cursor: pointer;
  }
  .menu-btn svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
  .menu-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

  .navlinks { display: none; }
  header.menu-open .navlinks {
    display: flex;
    flex-direction: column;
    gap: 2px;
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    right: 0;
    z-index: 60;
    padding: 8px;
    border: 1px solid var(--line2);
    border-radius: 14px;
    /* Solid panel over page content. Only some pages define --bg2; the literal is the same
       navy those pages use, so the panel looks identical everywhere. */
    background: var(--bg2, #0e1530);
    box-shadow: 0 24px 60px -12px rgba(0, 0, 0, 0.6);
  }
  header.menu-open .navlinks a { display: block; text-align: left; font-size: 15px; padding: 11px 13px; }
  /* The desktop nav breaks long labels over two lines ("Publisher<br>Solutions"); in a full-width
     panel row that break is noise. Each br has a space before it, so hiding it leaves "Publisher
     Solutions", not "PublisherSolutions". */
  header.menu-open .navlinks a br { display: none; }

  /* Footer: when the pages' 4-column footer collapses to 2 (their own ≤760px rule), the brand
     blurb stops sharing a row with a nav column — it takes a full-width row of its own, and its
     desktop 32ch cap comes off so the tagline actually runs across. */
  .fcols > .fbrand { grid-column: 1 / -1; max-width: none; }
}

/* Visually-hidden label for marks that stand ALONE (a table cell that is only a tick, a checklist
   verdict). An aria-hidden svg says nothing; this puts back what the glyph used to announce. */
.sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ---- (i) tooltips: the comparison tables' explain-this button and its one floating box ----
   Was pasted into three pages' inline <style>s; the pricing tables on /compare and the two
   competitor landers needed it too, so it lives here once. The box is position:fixed so a
   .tablewrap's overflow scroll cannot clip it; site.js positions it per button. */
.tip {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 1px solid var(--line2);
  background: transparent;
  color: var(--muted2);
  font-size: 10.5px;
  font-weight: 700;
  font-style: italic;
  font-family: Georgia, serif;
  display: inline-grid;
  place-items: center;
  cursor: help;
  vertical-align: 2px;
  margin-left: 7px;
  padding: 0;
}
/* A 16px circle is far below the 44px a thumb needs, and on a phone these buttons are the only
   way to reach the prices and the detail. The glyph keeps its size; an invisible pseudo-element
   does the catching, so nothing moves on screen. Phones only — on a pointer device a 44px
   invisible pad would swallow clicks meant for the text beside it. */
@media (max-width: 600px) {
  .tip {
    position: relative;
  }
  .tip::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
  }
}

.tip:hover,
.tip:focus {
  color: var(--steel);
  border-color: var(--steel);
  outline: none;
}
#tipbox {
  position: fixed;
  max-width: 290px;
  background: #0e1732;
  border: 1px solid var(--line2);
  border-radius: 10px;
  padding: 10px 13px;
  font-size: 12.5px;
  font-weight: 400;
  color: var(--muted);
  line-height: 1.55;
  z-index: 50;
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.5);
  pointer-events: none;
  display: none;
}

/* ---- Headings never strand a word on their last line ----
   "Five steps, ten minutes, no | cost." / "One API key and you're | live." — every page's h1/h2 had
   a max-width in ch that clipped a sentence a word short. Widths are set per page (below, in each
   page's <style>) so a sentence that fits one line gets one; this balances the ones that must wrap.
   The one-line intro under a heading gets the same treatment: two even lines, never a stub. */
h1,
h2,
h1 + p,
h2 + p {
  text-wrap: balance;
}
/* The one-line intro under a heading runs as wide as the points beneath it (760px). Each page caps
   its .sub/.lede at 600-640px, which folded a 15-word line into two short centred lines that sat
   narrower than the bullets under them. Specificity (h2 + p.sub) beats the page's .sub. */
h1 + p.lede,
h2 + p.lede,
h1 + p.sub,
h2 + p.sub {
  max-width: 760px;
}

/* ---- Points under a heading ----
   The intro under an h1/h2 is one line plus at most three points (CONTENT_GUIDELINES.md). The
   list is centered as a block, but the points inside are LEFT-JUSTIFIED and share one left edge —
   centered bullets float. Width fits the longest point (inline-grid), so the block still sits
   under the heading. Layout only; colour and size follow the page's own intro text. */
.pts {
  list-style: none;
  margin: 14px auto 0;
  padding: 0;
  max-width: 760px;
  display: grid;
  gap: 6px;
  justify-content: center;
  color: var(--muted);
  font-size: 16px;
  line-height: 1.5;
  text-align: left;
}
.pts li {
  /* A point that must wrap (narrow card, tablet) wraps into even lines, never a stub. */
  text-wrap: balance;
  /* Hanging dash via absolute positioning, not a grid: a point with inline children (a bound
     price span, a <b>) must stay one run of text, and grid/flex would split it into cells. */
  position: relative;
  padding-left: 22px;
}
.pts li::before {
  content: "—";
  position: absolute;
  left: 0;
  color: var(--steel);
}
.pts b {
  color: var(--ink);
  font-weight: 600;
}

/* Points inside a card: left-aligned to the card, sized like the card's body text.
   Named in-card, not .card — several pages already use .card for the box itself. */
.pts.in-card {
  margin: 0 0 14px;
  max-width: none;
  justify-content: start;
  gap: 4px;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--muted);
}

/* ---- Icon tiles and step numbers: centre the glyph, not its line box ----
   The tiles are display:grid / place-items:center, but the glyph inherited the body line-height
   (1.55), so the centred thing was a 32px line box with the emoji sitting high inside it. A
   line-height of 1 makes the box the glyph's own em square, and that is what gets centred. */
.whocard .ic,
.card .ic,
.step .n {
  line-height: 1;
}

/* ---- An icon on its own line is centred in its card ----
   Whether it is a tile (.whocard .ic), a bare emoji (.card .ic) or a security control glyph
   (.pcard .pi): when nothing sits to its right, it sits in the middle of the card, not hugging the
   left edge above a left-aligned title (Patrick, 2026-09-03). Icon-beside-title headers (.phead)
   are a different pattern and untouched. */
.whocard > .ic,
.card > .ic,
.pcard > .pi {
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}

/* ---- The competitor's charge, in red ----
   `.add` marks a price the competitor adds ("additional $0.35", "for a fee"). The commercial
   pages each defined it; /security did not and rendered its first "for a fee" in plain text.
   Defined once here; a page's own .add of equal specificity still wins where it exists. */
.add {
  color: var(--bad, #ff6b7d);
  font-weight: 600;
}

/* ---- A glyph with an (i) or a qualifier keeps the glyph centred ----
   .gl is the anchor: the tick / cross / dash sits in it and is centred by the cell like any other
   glyph; whatever accompanies it (.side: an (i), "for a fee", "8¢–15¢ (i)") is taken out of the
   flow and hung to the glyph's right, vertically level with it. Works whatever the cell's
   vertical alignment, so the ticks in a column line up whether or not a row explains itself. */
.gl {
  position: relative;
  display: inline-block;
}
.gl > .side {
  position: absolute;
  left: 100%;
  top: 50%;
  transform: translateY(-50%);
  margin-left: 8px;
  white-space: nowrap;
}
.gl > .side > .tip {
  margin-left: 7px;
}
.gl > .side > .tip:first-child {
  margin-left: 0;
}

/* ---- Step numbers follow the icon rule: on their own line, centred in the card ---- */
.step > .n,
.cstep > .cnum {
  display: grid;
  margin-left: auto;
  margin-right: auto;
}

/* ---- Nothing on the site scrolls sideways ----
   Tables have no min-width (their three columns share whatever width there is) and code snippets
   wrap. A horizontal scrollbar is a layout bug, not a feature (Patrick, 2026-09-03). */
.codeblock pre,
.codeblock code {
  white-space: pre-wrap;
  word-break: break-all;
}
td.cell,
td.feat,
th {
  /* break-word, not anywhere: words wrap at spaces first and only a token wider than the cell
     (a URL, a long compound) breaks inside itself — "included" must never render as "include/d". */
  overflow-wrap: break-word;
  hyphens: auto;
}
@media (max-width: 600px) {
  /* Fixed layout on a phone: every column is a fixed share of the screen and words wrap inside
     it (break-word applies to a token wider than its cell), so no table can outgrow the viewport.
     The shares themselves live in the phone-table block further down — one place, next to the
     measurements that justify them — not here. */
  table {
    table-layout: fixed;
  }
  td.cell {
    padding-left: 6px;
    padding-right: 6px;
  }
}

/* On a phone a column is too narrow to hang anything beside the glyph; the (i) / qualifier drops
   back into the flow and wraps, so the table never grows past the screen. */
@media (max-width: 600px) {
  .gl > .side {
    position: static;
    transform: none;
    margin-left: 6px;
    white-space: normal;
  }
}

/* ---- Under every price-comparison table: the negotiated-rate line ---- */
.negotiated {
  margin: 14px auto 0;
  max-width: 900px;
  text-align: center;
  font-size: 14px;
  color: var(--muted);
  text-wrap: balance;
}
/* The question itself is no longer bold — at 14px on a muted ground it read as heavy, not
   emphatic (Patrick, 2026-09-04). Only the link carries weight. */
.negotiated a {
  white-space: nowrap;
  color: var(--steel);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* The stacked-table treatment lived here until 2026-09-04. It turned each row into a labelled
   block on phones, and the homepage table was its only user. Removed with the class: side by side
   is the argument these tables make, so they keep the three-column grid on a phone and fold their
   explanatory sub-line into the (i) instead (site.js). Reinstating it means reinstating both. */


/* ---- The signup action in the header ----
   "Log in" is for people who already have an account; every page also needs the one action a
   logged-out visitor can take alone. Accent border so it reads as the action beside it, and the
   double class beats each page's own `nav a.login` skin without editing eleven inline styles. */
nav a.login.signup {
  color: var(--accent);
  border-color: var(--accent);
}
/* ---- The narrowest phones: "Sign up" moves into the menu ----
   At 320px (SE, split-screen) the header cannot hold brand + hamburger + two pills: the Sign up
   pill ended 41px past the screen and every page scrolled sideways. Below 380px the pill is
   hidden and the same action rides in the hamburger menu instead (the .menu-only anchor), so
   nothing is lost. .menu-only is display:none everywhere else, including desktop, where
   .navlinks is `display: contents`. */
.menu-only { display: none; }
@media (max-width: 380px) {
  header nav a.login.signup { display: none; }
  header.menu-open .navlinks .menu-only { display: block; }
}

/* Two pills in a row squeeze each other on a phone: without this, "Log in" and "Sign up" each
   break across two lines. `header nav` outranks every page's own `nav a.login` skin. */
header nav a.login {
  white-space: nowrap;
}
@media (max-width: 460px) {
  header nav a.login {
    padding-left: 9px;
    padding-right: 9px;
    margin-left: 4px;
  }
}

/* ---- Phone type scale ----
   Every page pins its h1 with a clamp whose FLOOR is 34-36px, so the headline never shrank below
   36px: at 320px "Get more. Reduce litigation. Less than half the cost." ran to five lines and a
   193px block, and the hero alone was 668px — taller than the screen (Patrick, 2026-09-04: "shrink
   the font more in mobile, it's way too big"). `body h1` outranks each page's bare `h1` rule, so
   this scales them all without editing eleven inline styles. */
@media (max-width: 480px) {
  /* `body .hero h1` as well as `body h1`: /security scopes its headline as `.hero h1`, which
     outranks a bare `body h1` and kept it at 40px on a phone while every other page scaled. */
  body h1,
  body .hero h1 {
    font-size: clamp(26px, 8.2vw, 33px);
  }
  body h2 {
    font-size: clamp(21px, 6.4vw, 26px);
  }
  /* Sub-headings and the hero lede ride the same curve. Body copy deliberately does NOT: 16px is
     the reading size, and under 16px iOS zooms the page whenever a form field takes focus (the
     /demo form), which reads as the layout jumping. */
  body h3,
  body .whocard h3,
  body .proof h3,
  body .step h3 {
    font-size: clamp(16px, 4.8vw, 19px);
  }
  body .lede {
    font-size: clamp(15.5px, 4.3vw, 17px);
  }
  /* A 12px floor: these all sat at 11-11.5px, which is below what a phone should ever render. */
  body tr.group td,
  body tr.group span,
  body .prow.phead .pcell,
  body .pcard .tag,
  body .field .fhint,
  body .rbadge,
  body .rrow .v,
  body .chip,
  body .op .auth,
  body .tbl th,
  body .tocbox h3,
  body .vstamp {
    font-size: 12px;
  }
}

/* ---- Phone tables: the column headers stay whole words ----
   The three columns are 42/29/29 of the screen, so a header cell was 76px wide with 18px of
   padding each side — 40px of usable width, which split "SafeBind" into "SafeB/ind" and
   "TrustedForm" into "Truste/dForm" (2026-09-04). Less padding and a slightly smaller header
   makes both fit on one line; `overflow-wrap: normal` stops the mid-word break, and the cells
   below keep break-word so a long price still wraps rather than overflowing. */
@media (max-width: 600px) {
  /* `table thead th`, not a bare `th`: every page sets its own `thead th { padding:16px 18px }`
     in an inline <style> that loads after this file, so a lower-specificity rule here loses. */
  table thead th {
    /* Measured, not guessed: "TrustedForm" at 12px is 76px, its (i) 16px, the gutter 4px and the
       padding 12px — 108px, which is what the 32% column below provides. No hyphenation either:
       a hyphen inside a product name reads as a typo. break-word stays as the last-resort valve
       so an over-long token can never overflow its cell. */
    font-size: 12px;
    padding-left: 4px;
    padding-right: 4px;
    hyphens: none;
  }
  /* The (i) drops onto its own line under the name. Beside it, "TrustedForm" + button + gutter
     needs ~105px of column, which can only come out of the label column; under it, the column has
     to fit the 76px word alone and the labels keep their width. */
  table thead th .tip {
    display: block;
    margin: 3px auto 0;
  }
  /* Same reason, plus /security's own `.col.us { width:13% }` and `.col:last-child { width:34% }`,
     which are two-class rules and beat a one-class override. On a phone a 22% (or 13%) column
     leaves ~40px of text and splits the brand names, so every comparison table gives its two data
     columns a third each here. */
  table thead th.col,
  table thead th.col.us,
  table thead th.col:last-child {
    width: 30%;
  }
  /* `table td.feat`, not a bare `td.feat`: the pages set `td.feat { padding:14px 18px }` in an
     inline <style> that loads after this file, so an equal-specificity rule here loses.
     Measured on /for-buyers at 390px: 18px of side padding left 96px of text in a 132px column,
     21 of 24 row labels wrapped onto 3+ lines, and the table ran 2,977px with a 119px median row.
     Tighter gutters, tighter leading and half a point off the label keep all three columns. */
  /* th.feat as well as td.feat: the homepage table marks its row label as a <th scope="row">,
     which kept the page's 18px padding and left 69px of text for an 79px word. */
  /* `clip`, not the wrapper's usual `auto`: the 44px tap pad on the last column's (i) reaches
     past the table's right edge, which grew the wrapper's scrollWidth by 5px and put a scrollbar
     under a table that fits. `clip` hides the pad (it is invisible anyway) without creating a
     scroll container. Phones only — on desktop the wrapper must still be able to scroll. */
  div.tablewrap {
    overflow-x: clip;
  }
  table td.feat,
  table th.feat,
  table td.cell {
    padding: 10px 8px;
    line-height: 1.35;
  }
  table td.feat,
  table th.feat {
    font-size: 13.5px;
  }
  /* A "prose" comparison table — both data columns hold sentences rather than a tick, so the
     label column gives up width instead of taking it, and the claims come down a point. Without
     this the homepage table wrapped "TrustedForm's" across two lines mid-word. */
  table.prose-cmp thead th.col,
  table.prose-cmp thead th.col.us {
    /* 34, not 37: at 37 the label column fell to 86px and broke "Unverifiable" and "Confusing"
       mid-word; 35 still clipped "Unverifiab/le" once letter-spacing is counted. 32/34/34 is the
       first split where neither column breaks a word at 390px. */
    width: 34%;
  }
  table.prose-cmp td.cell {
    font-size: 13px;
    hyphens: none;
  }
  /* The label column's longest words ("Unverifiable", "Prohibitively") need 90px at 13px once
     letter-spacing counts, and the column holds 89px. Half a point buys the margin — chasing it
     with column percentages just moved the break to the other side. */
  table.prose-cmp th.feat {
    /* 12px, the floor: "Prohibitively" is the longest label and still wanted one more pixel at
       12.5. Stop here — below the floor is worse than a wrap. */
    font-size: 12px;
    hyphens: none;
  }
}

/* At 360px and below a 30% column leaves 77px of text and "TrustedForm" (76px plus its
   letter-spacing) still tips onto a second line, so the label column gives up a little more. */
@media (max-width: 360px) {
  table thead th.col,
  table thead th.col.us,
  table thead th.col:last-child {
    width: 35%;
  }
}

/* ---- Phone footers: a link is a row, not a line ----
   The columns render 14px links 9px apart, so each target was 17-22px tall against a 44px
   guidance — the two Legal links in particular sit close enough to mis-tap. Padding rather than
   margin, so the whole row is the target and not just the text (Patrick, 2026-09-04: footer only;
   the header pills stay as they are, since raising them crowds the 320px header). */
@media (max-width: 600px) {
  footer .fcol a {
    padding: 11px 0;
    margin-bottom: 0;
  }
  footer .fcol h4 {
    margin-bottom: 4px;
  }
}

/* ---- The page cannot pan sideways ----
   Every horizontal overflow found in the 2026-09-04 audit is fixed at its cause, but nothing
   stopped the NEXT one from letting an iPhone drift left and right while scrolling — which is
   exactly what a stray `white-space: pre` did to the homepage in production. This is the belt to
   that braces: the root refuses to scroll horizontally, so a few stray pixels can never turn into
   a pannable page.

   `clip`, not `hidden`: hidden makes the element a scroll container, which breaks position:sticky
   (docs.html pins its contents box at ≥900px) and confuses scroll anchoring on iOS. clip just
   refuses the overflow.

   BOTH html and body, because html alone does nothing — measured, not assumed: with a deliberate
   600px element in a 390px viewport, `html { overflow-x: clip }` still panned 188px. The root's
   overflow propagates to the viewport and the root itself stays visible; it is body's value that
   ends up clipping. body alone works too; both are set so the rule survives someone later giving
   html an overflow of its own.

   This does NOT excuse an overflow — it hides one, so the measured checks at 320/360/390/768 stay
   the thing that proves a page is right. */
html,
body {
  overflow-x: clip;
}
