/* ══════════════════════════════════════════════════════════════════════════
   sf-gate.css — VANTA'S AGE GATE, dressed to the client's reference
   (owner brief, 2026-08-24: "an age gate similar to this reference with my
   client's branding" — refinedbiolabs.com, which is voice.references[0] in
   client.json and which the dev notes call his number one reference).

   WHAT THIS IS. `age-gate.js` is a PROTECTED ENGINE FILE — a front end never
   ships its own copy and never edits this one (engine/FRONTEND-CONTRACT.md §B).
   It is dressed instead through the seam documented in
   engine/AGE-GATE-THEMING.md: `--lag-*` custom properties plus `data-lag-*`
   copy slots. This file is that dressing. Not one line of age-gate.js changes,
   and the two attestation statements — the record the visitor affirms — are
   untouched, unmerged, both still unticked, and still the only thing that wakes
   the Confirm button. Those are not slots and this file does not try to make
   them one.

   §1 IS PURE TOKENS and is the bulk of the look. §2 is a small, deliberate
   override block for the four things the token set genuinely cannot reach:
   full-viewport bleed, which side the image lands on, the panel ratio, and the
   photograph's treatment. The theming doc says override CSS is not REQUIRED —
   it is not forbidden, and a card that must become an edge-to-edge interstitial
   needs it. Every rule there is scoped under `#lag-root`, because the engine
   appends its own <style> at inject time and therefore always wins on equal
   specificity; an ID is how a stylesheet linked in <head> gets a word in.

   ── COLOUR: NOTHING HERE IS A HEX (with two stated exceptions) ─────────────
   A concurrent session is re-deciding this client's sitewide palette. So every
   colour below resolves through the site's own `--sf-*` tokens and repaints
   itself when theme.css changes — there is no second palette to keep in sync.
   The two exceptions are named where they sit (§1 `--lag-aside-ink`, and the
   black scrim gradient over the photograph) and both are legibility floors over
   a dark photograph, not brand colours.

   The photograph itself is deliberately NEAR-MONOCHROME (see the provenance
   sidecar beside it): the brand tint is applied HERE, in CSS, mixed from
   `--sf-brand`. So a palette change re-tints the gate for free, and a grey
   brand simply reads as the neutral photograph it already is. That is the same
   reasoning AGE-GATE-THEMING.md §3a gives for the brand panel borrowing
   `--sf-brand` rather than carrying a colour of its own.

   ── MOBILE: THE FULL BLEED IS DESKTOP-ONLY, ON PURPOSE ────────────────────
   §2 is scoped to `min-width:841px`. Below the engine's own 840px breakpoint
   the gate keeps its stock stacking behaviour, and this file only tints the
   panel and sizes the type. That is not laziness: age-gate.js carries a long
   comment about a measured phone bug where the confirm button landed at y=972
   on a page that cannot scroll, leaving no way into the site at all. A
   hand-written `height:100vh` on a phone is exactly how that class of bug comes
   back, so this file does not write one.
   ══════════════════════════════════════════════════════════════════════════ */

/* ─────────────────────────────────────────────────────────────────────────
   §1 — TOKENS. The whole colour, type, radius and copy treatment.
   Resolution order for every one of these is documented in
   engine/AGE-GATE-THEMING.md §1: --lag-* → --sf-* → literal.
   ───────────────────────────────────────────────────────────────────────── */
:root {
  /* The gate is a full-page interstitial, not a card floating on a blurred
     site: the ground is the page surface and there is nothing to blur. The
     panels themselves paint everything the visitor sees. */
  --lag-scrim: var(--sf-elevated, #ffffff);
  --lag-scrim-blur: 0px;

  /* The action side. Straight off the site's own tokens — no gate palette. */
  --lag-surface: var(--sf-elevated, #ffffff);
  --lag-ink: var(--sf-text, #16272B);
  --lag-muted: var(--sf-muted, #4A6971);
  --lag-accent: var(--sf-accent, #2E6F7E);
  --lag-accent-text: var(--sf-accent-text, #ffffff);
  /* A solved hairline rather than a fixed grey: mixed from the page's own ink,
     so it stays a hairline on a light ground and on a dark one. */
  --lag-line: color-mix(in srgb, var(--sf-text, #16272B) 15%, transparent);

  /* Geometry. The reference is edge-to-edge with a pill primary and softly
     rounded attestation rows — so: no card corner, a pill button, a small
     radius on the boxes. */
  --lag-radius: 0px;
  --lag-btn-radius: 999px;
  /* The engine spends --lag-check-radius on the 21px tick BOX. §3 gives the
     attestation ROW its own, larger radius rather than reusing this one: at 8px
     a 21px box reads as a lozenge, and the reference pairs a nearly-square tick
     with a softly rounded row. Two radii because they are two shapes. */
  --lag-check-radius: 5px;
  --lag-row-radius: 10px;
  --lag-split-max: none;

  /* In the split the brand band has moved to the aside, so the header is not a
     band — it is the headline sitting on the card's own ground. */
  --lag-header-bg: transparent;
  --lag-header-ink: var(--sf-text, #16272B);

  /* Type. Both chains land on the site's own self-hosted faces; naming a family
     here would be a second font rule the build would have to police. */
  --lag-font-display: var(--sf-font-display);
  --lag-font-body: var(--sf-font-body);

  /* The mark sits top-left of the photograph, white, with no plate. The stock
     split puts it on a --sf-photo-bg plate because the aside is normally a flat
     brand FILL and a colour mark on a strong fill reads as a blob. This aside is
     a dark photograph with a scrim over it, which is exactly the ground a white
     silhouette is for — so the plate comes off and the filter goes back on. */
  /* 34px is the height a horizontal LOCKUP wants. Vanta's LOGO-NAV is 874x676 —
     a near-square MARK, not a lockup — so at 34px it reads as a small glyph
     rather than the brand. The engine's --sf-logo-lockup-scale (1.158, measured
     off this client's own artwork by logo-prep.mjs) is already multiplying this;
     40px takes it to ~46px rendered, which is the mark at a legible size on a
     half-viewport panel without competing with the aside headline. */
  --lag-logo-height: 40px;
  --lag-logo-filter: brightness(0) invert(1);
  --lag-logo-plate: transparent;
  --lag-logo-plate-radius: 0px;

  /* THE BRAND PANEL.
     --lag-aside-ink is one of this file's two literal colours. The stock chain
     solves it against --sf-brand, the flat FILL this panel normally wears; here
     the panel is a photograph, and no solver can answer for a photograph. The
     ground is guaranteed instead: the scrim gradients in --lag-aside-image are
     part of the same declaration and put a dark field under every character.
     White is the floor that ground was chosen to clear. */
  --lag-aside-ink: #FFFFFF;
  --lag-aside-ink-dim: color-mix(in srgb, #FFFFFF 74%, transparent);
  /* Under the photograph, and visible only in the moment before it decodes.
     Mixed from the brand so that moment is never a white flash. */
  --lag-aside-bg: color-mix(in srgb, var(--sf-brand, #16272B) 55%, #0B0D0E);

  /* THE PHOTOGRAPH, and the tint that makes it the client's.
     Read bottom-up: the frame, then a brand wash mixed from --sf-brand (this is
     what the reference does with its purple — the difference is that ours is
     solved from a token instead of baked into the pixels), then two scrims that
     guarantee the ground under the mark at the top and under the headline and
     proof row at the foot. All four layers take background-size:cover together,
     which is why the gradients are written to full height.

     THE WASH IS DELIBERATELY LIGHT, and this is the interesting part. The first
     pass set it at 46%, tuned against a teal brand. The palette then landed as
     near-black (--sf-brand #0B0D0F), and a 46% wash of near-black over an
     already-dark photograph is not a tint — it is a second scrim, and the glass
     stopped reading at all. The wash has to be quiet enough that a BLACK brand
     costs the photograph nothing, because that is the only value at which it is
     honestly a tint rather than a dimmer. A saturated brand still colours the
     panel at 22%; a black one now leaves it alone. Do not raise it to "make the
     tint show" without checking what it does to a dark brand. */
  --lag-aside-image:
    linear-gradient(180deg, rgba(6, 8, 9, 0.44) 0%, rgba(6, 8, 9, 0.10) 24%, rgba(6, 8, 9, 0) 40%),
    linear-gradient(0deg, rgba(6, 8, 9, 0.80) 0%, rgba(6, 8, 9, 0.34) 24%, rgba(6, 8, 9, 0) 54%),
    linear-gradient(158deg,
      color-mix(in srgb, var(--sf-brand, #16272B) 22%, transparent) 0%,
      color-mix(in srgb, var(--sf-brand, #16272B) 6%, transparent) 58%,
      transparent 100%),
    url("/brand_assets/gate-aside.webp");
}

/* ─────────────────────────────────────────────────────────────────────────
   §2 — THE FOUR THINGS TOKENS CANNOT REACH.
   Desktop only (see the header note on the phone bug this avoids).
   ───────────────────────────────────────────────────────────────────────── */
@media (min-width: 841px) {

  /* (a) FULL BLEED. The stock scrim centres a padded card; the reference is two
         panels meeting at the middle of the viewport with nothing around them. */
  html #lag-root {
    padding: 0;
    align-items: stretch;
    justify-content: stretch;
  }

  #lag-root .lag-modal.lag-split {
    max-width: none;
    width: 100%;
    min-height: 100vh;
    min-height: 100dvh;
    margin: 0;
    border-radius: 0;
    box-shadow: none;
    /* (c) PANEL RATIO — the reference reads as an even split, where the stock
           grid gives the action side the extra 6% it needs for two attestations
           at card width. At viewport width it does not need them. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }

  /* (b) WHICH SIDE THE IMAGE LANDS ON. The engine emits the brand panel first
         because stacked on a phone it is the introduction and belongs at the
         top of the reading order — which is still true, and is why this flip is
         inside the desktop query and is done with `order` rather than by moving
         a node. The DOM order, and therefore the screen-reader order, is
         unchanged. */
  #lag-root .lag-modal.lag-split > .lag-aside { order: 2; }
  #lag-root .lag-modal.lag-split > .lag-main  { order: 1; }

  /* (d) THE PHOTOGRAPH'S TREATMENT. background-position is the one thing the
         token cannot carry: --lag-aside-image sets the image, the engine sets
         `cover center`, and a 2:3 frame in a half-viewport panel wants its
         weight low and centred, not middled. */
  #lag-root .lag-aside {
    padding: 46px 48px 52px;
    background-position: center 58%;
    justify-content: flex-start;
  }

  /* ── the action side, laid out like the reference ─────────────────────── */

  /* Vertically centred, with the column held to a readable measure and offset
     from the panel edge the way the reference sets it. */
  #lag-root .lag-split .lag-main {
    justify-content: center;
    padding: 56px clamp(40px, 6vw, 96px);
  }
  #lag-root .lag-split .lag-head { padding: 0; max-width: 470px; width: 100%; align-self: center; }
  #lag-root .lag-split .lag-body { padding: 0; max-width: 470px; width: 100%; align-self: center; }

  /* The headline is the whole left panel's anchor in the reference — set very
     large, very tight, two lines, with the accent carried by a single full
     stop. The stock 1.42rem is a card headline. */
  #lag-root .lag-split .lag-headline {
    font-size: clamp(2.2rem, 3.6vw, 3.15rem);
    line-height: 1.03;
    letter-spacing: -0.035em;
    font-weight: 800;
  }

  #lag-root .lag-split .lag-intro {
    font-size: 0.95rem;
    line-height: 1.7;
    margin: 22px 0 30px;
    max-width: 27em;
  }

  /* The aside type scales with the panel it now fills. */
  #lag-root .lag-aside-headline { font-size: clamp(1.7rem, 2.1vw, 2.15rem); max-width: 15em; }
  #lag-root .lag-proof { padding-top: 22px; gap: 16px 22px; }
}

/* ─────────────────────────────────────────────────────────────────────────
   §3 — TREATMENT THAT IS RIGHT AT EVERY WIDTH.
   These are not layout; they are what the controls look like, and the
   reference's controls look the same on a phone as on a desktop.
   ───────────────────────────────────────────────────────────────────────── */

/* The engine mixes its woven wash for a flat brand FILL, where a 6–13% weave is
   texture. Over a photograph it is a visible diamond grid — measured on the
   phone shot, where the panel is a 350x243 band and the weave read as pattern
   sitting on top of the picture. Damped rather than switched off: it still
   carries the two corner pools that keep the mark's corner from going flat.
   NOT scoped to a breakpoint, because the photograph is there at every width —
   this rule was desktop-only in the first pass, which is exactly why the grid
   survived on the phone and nowhere else. */
#lag-root .lag-aside::before { opacity: 0.22; }

/* The accent full stop after the headline — the reference's one spot of brand
   colour on an otherwise achromatic panel. Decorative and generated, so it is
   not in the accessible name and not in the copy slot; set the headline slot
   without a trailing stop and this supplies it. */
#lag-root .lag-headline::after {
  content: ".";
  color: var(--sf-accent, #2E6F7E);
}

/* Attestation rows as bordered cards, which is the reference's treatment and
   also makes the hit target the whole row rather than the 21px box. The state
   colours stay on the accent chain, so a ticked row is visibly ticked in any
   palette. */
#lag-root .lag-check {
  align-items: flex-start;
  gap: 14px;
  margin-bottom: 12px;
  padding: 16px 18px;
  border: 1px solid var(--lag-line);
  border-radius: var(--lag-row-radius, 10px);
  background: var(--lag-surface, #ffffff);
  transition: border-color .15s ease, background .15s ease;
}
#lag-root .lag-check:hover {
  border-color: color-mix(in srgb, var(--sf-accent, #2E6F7E) 55%, transparent);
  background: color-mix(in srgb, var(--sf-accent, #2E6F7E) 5%, var(--lag-surface, #ffffff));
}
/* :has() is how a row can react to its own checkbox without a line of script.
   Unsupported browsers simply keep the hover treatment and the box's own tick —
   nothing is load-bearing here. */
#lag-root .lag-check:has(.lag-cb:checked) {
  border-color: color-mix(in srgb, var(--sf-accent, #2E6F7E) 70%, transparent);
  background: color-mix(in srgb, var(--sf-accent, #2E6F7E) 8%, var(--lag-surface, #ffffff));
}
#lag-root .lag-check:has(.lag-cb:focus-visible) {
  border-color: var(--sf-accent, #2E6F7E);
}
#lag-root .lag-txt { font-size: 0.875rem; line-height: 1.58; }

/* The reference has no rule between the last attestation and the button. */
#lag-root .lag-divider { display: none; }

/* The primary: a dark pill sized to its own label, not a full-width bar, with
   the reference's trailing arrow. It takes the page's INK rather than the
   accent — that is the reference's move (a near-black button under a coloured
   panel) and it is also the safer one while the palette is being re-decided,
   because ink-on-surface is the one pair the theme always solves. */
#lag-root .lag-btn-primary {
  width: auto;
  min-width: 210px;
  margin-top: 20px;
  padding: 15px 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.005em;
}
#lag-root .lag-btn-primary::after {
  content: "→";
  font-size: 1.05em;
  line-height: 1;
  transition: transform .18s cubic-bezier(.34, 1.45, .6, 1);
}
#lag-root .lag-btn-primary.ready {
  background: var(--sf-text, #16272B);
  color: var(--sf-elevated, #ffffff);
}
#lag-root .lag-btn-primary.ready:hover {
  background: color-mix(in srgb, var(--sf-text, #16272B) 86%, var(--sf-elevated, #ffffff));
}
#lag-root .lag-btn-primary.ready:hover::after { transform: translateX(3px); }
/* Idle keeps the engine's own tinted-ink plate; only the arrow is quietened so
   a disabled control does not advertise a direction it will not go. */
#lag-root .lag-btn-primary:not(.ready)::after { opacity: .45; }

/* Fine print: left-aligned under the button, in the reference's small measure. */
#lag-root .lag-fine {
  margin-top: 18px;
  font-size: 0.735rem;
  line-height: 1.6;
  max-width: 34em;
}

/* The way out is a sentence with a link in it, not a second big button
   competing with the primary. The copy slot carries the sentence
   ("Not a researcher? Exit"); this makes it read like one. */
#lag-root .lag-btn-secondary {
  width: auto;
  margin-top: 22px;
  padding: 2px 0;
  border: 0;
  border-radius: 0;
  background: none;
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--lag-muted, #4A6971);
  text-align: left;
  display: inline-block;
}
#lag-root .lag-btn-secondary:hover {
  border: 0;
  color: var(--sf-text, #16272B);
  text-decoration: underline;
  text-underline-offset: 3px;
}
#lag-root .lag-btn-secondary:focus-visible {
  outline: 2px solid var(--sf-accent, #2E6F7E);
  outline-offset: 3px;
  border-radius: 3px;
}

/* Stacked, the brand panel is a band above the card rather than a full-height
   panel — give the photograph enough height to be a photograph. */
@media (max-width: 840px) {
  #lag-root .lag-aside {
    min-height: 210px;
    background-position: center 55%;
    justify-content: flex-end;
  }
  #lag-root .lag-btn-primary { width: 100%; }
}

/* The gate is a hard stop in front of the site: it appears, it does not
   perform. Mirrors the engine's own reduced-motion block. */
@media (prefers-reduced-motion: reduce) {
  #lag-root .lag-btn-primary::after,
  #lag-root .lag-btn-primary.ready:hover::after { transition: none; transform: none; }
}
