/* ============================================================================
   LIFEPOLICIES-HELP — LOAD-BEARING
   A limestone wall section, lit from above, in which the only thing carrying
   real mass is the part of the policy that is actually in the contract.

   One rule governs every content mark on this page:
     solid + opaque            = stated in the contract  (guaranteed)
     dotted / dashed / hatched = can change               (not guaranteed)
   Colour never encodes certainty. Only material does.

   Interactive controls sit OUTSIDE that system — see "button carve-out".
   ========================================================================= */

/* ---------------------------------------------------------------- fonts -- */

/* Archivo alone is `optional`, not `swap`. It sets the h1, and the h1 carries
   text-wrap: balance — so a face that arrives after first paint can re-break a
   three-line headline and move both CTAs down the fold under a thumb already on
   its way to one. The latin subset is preloaded, so it normally wins the 100ms
   block period; when it does not, this pageview is set in the fallback rather
   than reflowed halfway through. Literata keeps `swap`: it sets no heading, and
   the reading column reflowing is not the fold moving. */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: optional;
  src: url('../fonts/archivo-var-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: optional;
  src: url('../fonts/archivo-var-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('../fonts/literata-var-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('../fonts/literata-var-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --------------------------------------------------------------- tokens -- */
/*
 * Hue law: every neutral is biased green-grey. Never warm/beige (lands in the
 * cream cluster), never blue-grey (lands in fintech navy). Light neutrals are
 * limestone; dark neutrals are wet slate.
 */

:root {
  --ground: #e1e4dc;
  --ground-deep: #d2d6cc;
  --plane: #f0f2ec;
  --ink: #171c1a;
  --ink-2: #3e4642;
  --rule: #99a096;

  /* Semantic certainty tokens — material, not decoration.
     The non-guaranteed ink is dark enough that a hatched patch and a solid one
     read as the same weight of statement. A hatch lays down a fraction of its
     ink over the ground, so the pale value this used to carry (3.6:1) put every
     caveat on the page below every guarantee — the one thing the material rule
     is not allowed to do. */
  --mark-g: #171c1a;
  --mark-n: #545c54;

  /* The accent. Four permitted uses: the primary CTA, the tel: link, the
     staffed-hours tab, and the drawn underline under one word of the headline.
     It never touches a certainty mark and never enters .tl-fig. */
  --signal: #8e3a29;
  --signal-deep: #6e2a1d;
  --signal-on: #f0f2ec;

  /* Interactive controls need a boundary that clears 3:1 against their own
     fill; --rule is a structural hairline and deliberately does not. */
  --rule-control: #6c746c;

  /* Semantic, not the accent. Validation state is not a claim about a policy,
     and it is not one of --signal's three permitted uses. */
  --alert: #9d3324;
  --alert-ink: #171c1a;

  --focus-a: #171c1a;
  --focus-b: #f0f2ec;

  /* Photography is graded toward the page rather than dropped on top of it. */
  --img-filter: saturate(0.76) contrast(1.03);
  --img-veil: 0.1;

  /* Light comes from above: a lifted plane casts along its BOTTOM edge. */
  --cast: 0 1px 0 rgba(23, 28, 26, 0.14);
  --cast-inset: inset 0 1px 0 rgba(23, 28, 26, 0.1);


  /* The closing band's own palette. Deliberately not aliased to --ink: a rule
     cannot both set --ink and read var(--ink) for its background. */
  --terminal-bg: #171c1a;
  --terminal-plane: #232b28;
  --terminal-ink: #e1e4dc;
  --terminal-ink-2: #a5aba2;
  --terminal-rule: #59615a;
  --terminal-mark-n: #8d958b;
  /* Brick on #171c1a is 2.29:1, so the closing band's accent has to be remapped
     — but it used to borrow the DARK theme's accent wholesale, which flipped
     both the hue family and the label polarity on the last and most decisive
     CTA on the page: near-white label on brick everywhere above, near-black
     label on salmon here. Same family, same polarity.

     #c05235 held the family and the polarity but only reached 4.14:1 against
     the near-white label, which is a fail: .tl-btn sets 17px at weight 600 and
     that is not WCAG large text. Measured, not estimated. */
  --terminal-signal: #a8462c; /* 5.20:1 against --terminal-signal-on */
  /* Hover darkens, as it does everywhere else on the page. It used to lighten,
     which was correct against a near-black label and is 2.58:1 against a
     near-white one — the slab would have got brighter as the words on it
     disappeared. */
  --terminal-signal-deep: #8e3a24;
  --terminal-signal-on: #f0f2ec;

  --mark-plate: #f0f2ec;

  --shell: 1200px;
  --gutter: 24px;
  --margin: 32px;
  --stub: 192px;
}

/*
 * Dark is a change of light, not an inversion: the same green-grey hue family
 * seen in a low-lit room. A lifted plane is LIGHTER than ground and catches a
 * rim along its TOP edge, because the light still comes from above.
 */
@media (prefers-color-scheme: dark) {
  :root {
    --ground: #141917;
    --ground-deep: #0d1110;
    --plane: #1e2422;
    --ink: #dde0d8;
    --ink-2: #a5aba2;
    --rule: #59615a;
    --mark-g: #dde0d8;
    /* Pulled back as the hatch pitch tightened, so a hatched patch weighs the
       same in both themes rather than being the stronger mark in dark. */
    --mark-n: #7d857b;
    --signal: #d0654a;
    --signal-deep: #e07c60;
    --signal-on: #0d1110;
    --rule-control: #99a196;
    --alert: #e08a72;
    --alert-ink: #dde0d8;
    --focus-a: #dde0d8;
    --focus-b: #0d1110;
    --img-filter: saturate(0.66) contrast(1.02) brightness(0.82);
    --img-veil: 0.16;
    --cast: 0 -1px 0 rgba(221, 224, 216, 0.1);
    --cast-inset: inset 0 1px 0 rgba(0, 0, 0, 0.28);

    /* On a dark page the terminal beat comes from stepping UP into a lit
       surface, not from flipping to white. */
    --terminal-bg: #242c29;
    --terminal-plane: #2e3733;
    /* The light theme darkens its terminal accent to clear 4.5:1 against a
       near-white label. On a dark page that band is already a lit surface and
       the page's own accent reads correctly on it, so dark keeps the accent it
       uses everywhere else — 5.11:1, and one red per theme rather than two. */
    --terminal-signal: #d0654a;
    --terminal-signal-deep: #e07c60;
    --terminal-signal-on: #0d1110;
    --mark-plate: #e8eae2;
  }
}

/* The viewer's toggle must win over the OS preference in BOTH directions. */
:root[data-theme='dark'] {
  --ground: #141917;
  --ground-deep: #0d1110;
  --plane: #1e2422;
  --ink: #dde0d8;
  --ink-2: #a5aba2;
  --rule: #59615a;
  --mark-g: #dde0d8;
  --mark-n: #7d857b;
  --signal: #d0654a;
  --signal-deep: #e07c60;
  --signal-on: #0d1110;
  --rule-control: #99a196;
  --alert: #e08a72;
  --alert-ink: #dde0d8;
  --focus-a: #dde0d8;
  --focus-b: #0d1110;
  --img-filter: saturate(0.66) contrast(1.02) brightness(0.82);
  --img-veil: 0.16;
  --cast: 0 -1px 0 rgba(221, 224, 216, 0.1);
  --cast-inset: inset 0 1px 0 rgba(0, 0, 0, 0.28);
  --terminal-bg: #242c29;
  --terminal-plane: #2e3733;
  --terminal-signal: #d0654a;
  --terminal-signal-deep: #e07c60;
  --terminal-signal-on: #0d1110;
  --mark-plate: #e8eae2;
}

:root[data-theme='light'] {
  --ground: #e1e4dc;
  --ground-deep: #d2d6cc;
  --plane: #f0f2ec;
  --ink: #171c1a;
  --ink-2: #3e4642;
  --rule: #99a096;
  --mark-g: #171c1a;
  --mark-n: #545c54;
  --signal: #8e3a29;
  --signal-deep: #6e2a1d;
  --signal-on: #f0f2ec;
  --rule-control: #6c746c;
  --alert: #9d3324;
  --alert-ink: #171c1a;
  --focus-a: #171c1a;
  --focus-b: #f0f2ec;
  --img-filter: saturate(0.76) contrast(1.03);
  --img-veil: 0.1;
  --cast: 0 1px 0 rgba(23, 28, 26, 0.14);
  --cast-inset: inset 0 1px 0 rgba(23, 28, 26, 0.1);
  --terminal-bg: #171c1a;
  --terminal-plane: #232b28;
  --terminal-signal: #a8462c;
  --terminal-signal-deep: #8e3a24;
  --terminal-signal-on: #f0f2ec;
  --mark-plate: #f0f2ec;
}

/* ---------------------------------------------------------------- reset -- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* Several utilities here set an explicit `display`, which would otherwise beat
   the UA stylesheet's [hidden] rule and leave both hours states on screen. */
[hidden] {
  display: none !important;
}

html {
  /* A page that argues it sets numbers honestly sets its five numbers right. */
  font-variant-numeric: tabular-nums lining-nums;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--ground);
  overflow-wrap: break-word;
  color: var(--ink);
  font-family: 'Literata', Georgia, 'Times New Roman', serif;
  font-size: 1.09375rem; /* 17.5px */
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img,
svg {
  display: block;
  max-width: 100%;
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

/* Radius is 0 everywhere. The only exception is 2px on the two CTA slabs. */
:where(button, input, select, fieldset, textarea) {
  border-radius: 0;
}

fieldset {
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

legend {
  padding: 0;
}

hr {
  border: 0;
  margin: 0;
}

::selection {
  background: var(--ink);
  color: var(--ground);
}

/* ------------------------------------------------------------ typography -- */

/*
 * The headline and the six section heads are sized against each other, not
 * independently. The section head used to be a flat 38px while the h1's 3.4vw
 * did not reach 38px until a 1118px viewport — so across the whole tablet and
 * small-laptop band the headline was the SMALLER display object on its own
 * page. Both are now clamped on the same viewport axis: 3.4 / 2.6 = 1.31, so
 * the ratio is fixed through the fluid band, and the two floors (34/24) and the
 * two ceilings (50/38) are set further apart than that, never closer.
 */
.tl-h1 {
  margin: 0;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 118%;
  font-size: clamp(2.125rem, 3.4vw, 3.125rem);
  line-height: 1.05;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

.tl-section-head {
  margin: 0;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 118%;
  font-size: clamp(1.5rem, 2.6vw, 2.375rem);
  line-height: 1.1;
  letter-spacing: -0.012em;
  text-wrap: balance;
}

.tl-kicker {
  margin: 0;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 100%;
  font-size: 1.5rem;
  line-height: 1.3;
  letter-spacing: -0.005em;
  text-wrap: balance;
}

.tl-numeral {
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 112%;
  font-size: 1.875rem;
  line-height: 1.1;
  letter-spacing: -0.01em;
}

.tl-lead {
  margin: 0;
  font-size: 1.25rem;
  line-height: 1.5;
  max-width: 46ch;
}

/* Literata's figures are much wider than its average lowercase, so a `ch` here
   buys about 18% more measure than it reads as: 68ch was setting 80 characters
   to the line. Every measure on the page is counted off the render rather than
   trusted to the unit. */
.tl-prose {
  margin: 0;
  font-size: 1.09375rem;
  line-height: 1.65;
  max-width: 58ch;
}

/* Disclosures are the most carefully set type on this page, not fine print. */
.tl-legal {
  margin: 0;
  font-size: 0.84375rem; /* 13.5px */
  line-height: 1.6;
  color: var(--ink-2);
  max-width: 62ch;
}

.tl-label,
.tl-micro {
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 87%;
  text-transform: uppercase;
  color: var(--ink-2);
  display: block;
}

.tl-label {
  font-size: 0.84375rem;
  letter-spacing: 0.1em;
  line-height: 1.3;
}

.tl-micro {
  font-size: 0.78125rem; /* 12.5px */
  letter-spacing: 0.12em;
  line-height: 1.3;
}

/* Literata never sets a heading, never goes above 20px, is never letterspaced. */

a {
  color: inherit;
}

.tl-link {
  color: var(--ink);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

.tl-link:hover {
  color: var(--ink-2);
}

/* The tel: link is one of the accent's four permitted uses. */
.tl-tel {
  color: var(--signal);
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 100%;
  text-decoration: underline;
  text-decoration-color: var(--signal-deep);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  white-space: nowrap;
}

.tl-tel:hover {
  color: var(--signal-deep);
}

/* --------------------------------------------------------------- layout -- */

.tl-stratum {
  /* Strata are full-bleed and separated by a hard cast edge, never by margin. */
  background: var(--ground);
  border-bottom: 1px solid var(--rule);
}

.tl-stratum--deep {
  background: var(--ground-deep);
}

.tl-stratum--plane {
  background: var(--plane);
  box-shadow: var(--cast);
}

.tl-shell {
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--margin);
}

.tl-band {
  padding-block: 96px;
}

.tl-band--tight {
  padding-block: 56px;
}

/* The stub/field split, borrowed from a policy illustration's row labels.
   Used on exactly two sections: How it works, and the FAQ. */
.tl-split {
  display: grid;
  grid-template-columns: var(--stub) minmax(0, 1fr);
  gap: var(--gutter);
}

.tl-skip {
  position: absolute;
  left: -9999px;
}

.tl-skip:focus {
  position: fixed;
  left: 16px;
  top: 16px;
  z-index: 100;
  background: var(--ink);
  color: var(--ground);
  padding: 12px 20px;
  font-family: 'Archivo', sans-serif;
  font-stretch: 87%;
  font-size: 0.84375rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

/* ---------------------------------------------------- the certainty marks -- */
/*
 * Two invariants:
 *   1. Non-guaranteed content is never made quieter — no opacity reduction,
 *      no smaller type, no lower contrast. It differs in material, not volume.
 *   2. Non-guaranteed is dot / dash / hatch — never a plain outline. That is
 *      what keeps an outlined BUTTON from reading as a certainty claim.
 *
 * A lattice mark has to POINT at the cell it heads, not merely classify it.
 * Four of the six used to be bare key swatches or generic pictograms, which is
 * why the grid needed a legend above it teaching a reading three of the six
 * then contradicted. Each mark below draws the thing its cell is about, in the
 * material that thing actually has.
 *
 * 1.5 of ink every 4px is the pitch everywhere a hatch appears, in CSS and in
 * the SVG pattern. The old 1-in-5 put only 20% coverage on the ground, so a
 * hatched patch averaged out close to the page while a solid one did not — the
 * material rule reading as a volume difference.
 */

.tl-mark {
  display: block;
  width: 56px;
  height: 40px;
  flex: none;
}

/* A guaranteed minimum beside a non-guaranteed part. Left/right rather than the
   footer key's stacked version, deliberately: this cell's heading is literally
   "side by side" and the key's own sentence is literally "above it". */
.tl-mark--split {
  background: linear-gradient(to right, var(--mark-g) 0 50%, transparent 50% 100%),
    repeating-linear-gradient(45deg, transparent 0 2.5px, var(--mark-n) 2.5px 4px);
  border-right: 1.25px dotted var(--mark-n);
  border-top: 1.25px dotted var(--mark-n);
  border-bottom: 1.25px dotted var(--mark-n);
}

/* Charges: your money with pieces taken out of it. Not the three ascending
   solid bars this used to be — ascending bars are the universal glyph for
   growth, so on a life page they argued the opposite of the cell they headed.
   The block is solid because the contract states the maximum charges; the band
   left at the top is hatched because what the carrier deducts inside those
   maximums is a current figure it can raise. */
.tl-mark--charges {
  /*
   * The cuts are thin and the segments are not. An earlier pass spaced three
   * 6px bars over three 4px gaps and detached the hatch band above them by a
   * fourth gap, which at 56x40 is the geometry of a hamburger menu — four
   * evenly weighted horizontal bars — sitting over the words "What the policy
   * actually costs". A block with slices taken out of it has to still read as a
   * block: solid runs of 11, 6, 5 and 4px, cut by 2.5px, and the hatch band
   * flush against the top of the solid rather than floating above it.
   */
  background: linear-gradient(
      to top,
      var(--mark-g) 0 11px,
      transparent 11px 13.5px,
      var(--mark-g) 13.5px 19.5px,
      transparent 19.5px 22px,
      var(--mark-g) 22px 27px,
      transparent 27px 29.5px,
      var(--mark-g) 29.5px 34px,
      transparent 34px 100%
    ),
    repeating-linear-gradient(45deg, transparent 0 2.5px, var(--mark-n) 2.5px 4px);
  background-size: 100% 100%, 100% 6px;
  background-position: bottom, top;
  background-repeat: no-repeat;
  box-shadow: var(--cast);
}

/* Index crediting: the hero drawing's bar-inside-its-outline at 56x40. The
   dotted rectangle is how far the index moved, the hatch is the share of it
   that was credited — the same two objects in the same two materials as the
   figure 800px up the page, which is the whole point of reusing it here.
   Neither quantity is promised, so neither is solid. */
.tl-mark--idx {
  background: repeating-linear-gradient(
    45deg,
    transparent 0 2.5px,
    var(--mark-n) 2.5px 4px
  );
  background-size: 100% 60%;
  background-position: bottom;
  background-repeat: no-repeat;
  border: 1.25px dotted var(--mark-n);
}

/* Sustained funding: the same premium, over and over. Seven bars on 8px
   centres, the first five solid because the premium the design needs is a
   stated requirement, the last two hatched because nobody has committed to
   them — and stopping is exactly what the cell says makes these policies fail. */
.tl-mark--premiums {
  background: repeating-linear-gradient(
      45deg,
      transparent 0 2.5px,
      var(--mark-n) 2.5px 4px
    ),
    repeating-linear-gradient(45deg, transparent 0 2.5px, var(--mark-n) 2.5px 4px),
    repeating-linear-gradient(to right, var(--mark-g) 0 4px, transparent 4px 8px);
  background-size: 4px 100%, 4px 100%, 40px 100%;
  background-position: 50px 0, 42px 0, 2px 0;
  background-repeat: no-repeat;
}

/* Cash value drawn down by a loan: solid mass decaying to a hairline. A loan
   against the policy is a contractual mechanic, so it is solid throughout. */
.tl-mark--wedge {
  background: var(--mark-g);
  clip-path: polygon(0 0, 100% 72%, 100% 100%, 0 100%);
}

/* Two routes, not two halves of one thing. A solid box on the baseline — term
   or guaranteed UL, whose cost is a contract term — and a hatched, dotted one
   raised beside it, whose crediting is not. The different baselines are what
   stop this reading as the split block above with a gap cut into it; the cell
   lists four alternatives, none of which is a guaranteed/non-guaranteed pair. */
.tl-mark--routes {
  display: flex;
  align-items: flex-end;
  gap: 8px;
}

.tl-mark--routes::before,
.tl-mark--routes::after {
  content: '';
  flex: 1;
  height: 30px;
}

.tl-mark--routes::before {
  background: var(--mark-g);
  box-shadow: var(--cast);
}

.tl-mark--routes::after {
  margin-bottom: 10px;
  background: repeating-linear-gradient(
    45deg,
    transparent 0 2.5px,
    var(--mark-n) 2.5px 4px
  );
  border: 1.25px dotted var(--mark-n);
}

/* ---------------------------------------------------------------- chips -- */

.tl-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 87%;
  font-size: 0.78125rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
  line-height: 1.2;
}

/*
 * The glyph was 22x12 with the split painted left/right, which gave the hatched
 * half eleven pixels — about two strokes — so BOTH rendered as IN THE CONTRACT
 * with a frayed edge and nine repetitions of the mark could not sort the list
 * it heads. Wider, taller, and a tighter 2-in-3 pitch that this file uses
 * nowhere else, because at 14px a 2.5-in-4 hatch is four strokes and reads as
 * damage rather than as texture.
 */
.tl-chip::before {
  content: '';
  width: 30px;
  height: 14px;
  flex: none;
}

.tl-chip--g::before {
  background: var(--mark-g);
}

.tl-chip--n::before {
  background: repeating-linear-gradient(
    45deg,
    transparent 0 2px,
    var(--mark-n) 2px 3px
  );
  border: 1.25px dotted var(--mark-n);
}

/* Stacked to agree with the footer key's sentence — a guaranteed minimum with a
   non-guaranteed part ABOVE it — and with the drawing, which stacks. The 1px
   hairline is what makes the two halves read as two materials: without it the
   hatch runs its diagonals into the solid half and the boundary between them is
   a ragged edge rather than a stated one. */
.tl-chip--split::before {
  background: linear-gradient(
      to top,
      var(--mark-g) 0 50%,
      var(--ink) 50% calc(50% + 1px),
      transparent calc(50% + 1px) 100%
    ),
    repeating-linear-gradient(45deg, transparent 0 2px, var(--mark-n) 2px 3px);
  border-top: 1.25px dotted var(--mark-n);
}

.tl-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 28px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* --------------------------------------------------------------- header -- */

.tl-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  min-height: 56px;
  padding-block: 12px;
  flex-wrap: wrap;
}

.tl-wordmark {
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  text-decoration: none;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 112%;
  font-size: 1.125rem;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.tl-wordmark span {
  font-stretch: 87%;
  font-size: 0.78125rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
  font-weight: 600;
}

.tl-header-right {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}

/* ----------------------------------------------------------------- hero -- */
/*
 * The film leads. It is the first thing on the page and it runs full-bleed,
 * with the words on an opaque panel laid over its lower edge rather than set
 * directly on the footage.
 *
 * That panel is not decoration. Type on moving video is the one place a page
 * like this cannot honour its own contrast rule — the ratio changes every
 * frame, and the frames this clip is graded from are low-key. Everything a
 * visitor has to read to decide sits on --plane at the same contrast it has
 * everywhere else on the site; the film carries the feeling and none of the
 * argument. It is also why no disclosure, no legal line and no certainty mark
 * is ever laid over the footage.
 */

.tl-hero-film {
  position: relative;
  display: grid;
  /* One cell. The media and the shell stack in it, so the panel's height sets
     the section's height and nothing is positioned by magic number. */
  grid-template-areas: 'stack';
  isolation: isolate;
  background: var(--ground-deep);
  /* Tall enough to read as the page opening on a film rather than on a band of
     one, capped so a short laptop still gets the first question on the fold. */
  min-height: min(76vh, 740px);
}

.tl-hero-film > * {
  grid-area: stack;
  min-width: 0;
}

.tl-hero-media {
  position: relative;
  overflow: hidden;
  /* The clip is 16:9. Below the panel's overlap the section is allowed to run
     taller than the footage and the film crops rather than letterboxes. */
  min-height: 100%;
}

.tl-hero-media img,
.tl-hero-media video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The three faces sit in the middle band of the frame; on a tall crop the
     default 50% centre would cut the grandfather's eyeline. */
  object-position: 50% 38%;
  /*
   * The film gets its OWN grade, not --img-filter. That token exists to pull a
   * warm stock still toward the limestone palette in a 400px box further down
   * the page; applied to a full-bleed moving frame it reads as fog, and the one
   * asset the page now opens on cannot be the one that looks washed out.
   * Barely desaturated, barely lifted — it still sits in the page's light.
   */
  filter: saturate(0.88) contrast(1.06);
}

/*
 * A scrim, not a veil. Bottom-heavy, so the panel's top edge lands on the
 * darker part of the frame and its 1px rule stays visible, and so the section's
 * lower boundary settles into the band below instead of stopping dead.
 *
 * There is deliberately no wash of --ground over the footage. The film is the
 * one thing on this page that is allowed to be an image rather than a material,
 * and flattening it into the palette costs exactly the thing it was moved up
 * here to provide.
 */
.tl-hero-media::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    rgba(13, 17, 16, 0.34) 0%,
    rgba(13, 17, 16, 0.08) 38%,
    rgba(13, 17, 16, 0.1) 62%,
    rgba(13, 17, 16, 0.44) 100%
  );
}

.tl-hero-inner {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: end;
  pointer-events: none; /* the film keeps its own hit area; the panel re-enables */
  padding-block: 88px 56px;
}

.tl-hero-inner > .tl-shell {
  width: 100%;
}

/* The film swaps in over the poster once page.js has decided it may load. Both
   sit in the same box; the poster stays underneath as the first paint and as
   the fallback if the clip never arrives. */
.tl-hero-media picture,
.tl-hero-media video {
  position: absolute;
  inset: 0;
}

.tl-hero-media video {
  opacity: 0;
  transition: opacity 220ms linear;
}

.tl-hero-media video.is-playing {
  opacity: 1;
}

/*
 * The panel. Hard 1px edge and zero radius like every other surface here — it
 * is a lifted plane, so on a light page it casts along its bottom edge and on
 * a dark one it catches a rim along its top. Nothing about it is a card.
 */
.tl-hero-panel {
  pointer-events: auto;
  width: 100%;
  max-width: 620px;
  display: flex;
  flex-direction: column;
  align-items: start;
  gap: 22px;
  padding: 36px 36px 40px;
  background: var(--plane);
  border: 1px solid var(--rule);
  box-shadow: var(--cast);
}

.tl-hero-panel > * {
  margin: 0;
}

/*
 * The trust line, above the headline rather than below the fold. Every clause
 * in it is checkable by the visitor: the register is public, and the licence
 * number is read out on the call. It carries no certainty material — it is a
 * statement about the agency, not about a policy.
 */
.tl-hero-trust {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 2px;
  border-bottom: 1px solid var(--ink);
}

.tl-hero-trust::before {
  content: '';
  width: 14px;
  height: 14px;
  flex: none;
  background: var(--mark-g);
  box-shadow: var(--cast);
}

/* The film's own control. Sits on the footage, top-right, clear of the panel. */
.tl-hero-toggle {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  background: var(--plane);
  border: 1px solid var(--rule-control);
  border-radius: 0;
  cursor: pointer;
  transition: border-color 90ms linear;
}

.tl-hero-toggle:hover {
  border-color: var(--ink);
}

.tl-hero-toggle .tl-video-glyph {
  display: block;
  width: 12px;
  height: 14px;
}

.tl-hero-toggle[data-playing='true'] .tl-video-glyph {
  background: linear-gradient(
    to right,
    var(--ink) 0 35%,
    transparent 35% 65%,
    var(--ink) 65% 100%
  );
}

.tl-hero-toggle[data-playing='false'] .tl-video-glyph {
  background: var(--ink);
  clip-path: polygon(0 0, 100% 50%, 0 100%);
}

/* With no scripting the clip never loads and the poster is the whole story, so
   there is nothing to pause and the control would be a dead button. */
html:not(.tl-js) .tl-hero-toggle {
  display: none;
}

.tl-trust {
  display: grid;
  grid-template-columns: repeat(3, auto);
  justify-content: start;
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 0.875rem;
  line-height: 1.45;
  color: var(--ink-2);
}

.tl-trust li {
  padding-inline: 14px;
  border-left: 1px solid var(--rule);
}

.tl-trust li:first-child {
  padding-left: 0;
  border-left: 0;
}

/* ----------------------------------------------------- the drawn line --- */
/*
 * A hand-drawn stroke that draws itself in. One flourish under a word in the
 * headline, and one thread running down the four steps of the process.
 *
 * THIS IS AN AMENDMENT TO TWO STANDING RULES. Both are narrowed rather than
 * dropped, and the narrowing is the whole point:
 *
 * 1. "Self-drawing strokes are deliberately absent — a line that draws itself
 *    over time reads as an illustration playing out." That reasoning is about
 *    the crediting figure, where a stroke arriving over time would imply values
 *    accruing over time, which is exactly the claim this page may not make.
 *    So the rule now reads: NOTHING INSIDE .tl-fig, AND NOTHING CARRYING
 *    CERTAINTY MATERIAL, EVER DRAWS ITSELF. The diagram still renders complete;
 *    its non-guaranteed marks still only fade. A flourish under a headline word
 *    and a thread beside four numbered steps make no claim about a policy, so
 *    they are free to be drawn.
 *
 * 2. The accent's permitted uses go from three to four: the primary CTA, the
 *    tel: link, the staffed-hours tab, and this flourish. The invariant that
 *    mattered is untouched — the accent still never touches a certainty mark,
 *    never enters the figure, and may never colour a projection. A stroke under
 *    a word in a sentence is not a value.
 *
 * The thread is --ink, not the accent: it runs beside step four, which carries
 * non-guaranteed material, and the accent may not sit that close to a mark.
 *
 * Geometry is authored on a pathLength="1" path so the dash maths is the same
 * whatever the path actually measures.
 */

.tl-draw {
  display: block;
  overflow: visible;
  pointer-events: none;
}

.tl-draw path {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

/* The headline flourish. Two passes, the way a marker doubles back. */
.tl-draw--underline {
  position: absolute;
  left: 0;
  bottom: -0.18em;
  width: 100%;
  height: 0.34em;
}

.tl-draw--underline path {
  stroke: var(--signal);
  stroke-width: 3;
}

.tl-draw--underline path:nth-child(2) {
  stroke-width: 2;
  opacity: 0.55;
}

/* A word that carries a flourish needs to be its own positioning context, and
   it must not break across a line or the stroke lands under half of it. */
.tl-mark-word {
  position: relative;
  display: inline-block;
  white-space: nowrap;
}

/* The process thread, drawn down the stub gutter beside the four steps. */
.tl-steps-wrap {
  position: relative;
}

.tl-draw--thread {
  position: absolute;
  top: 32px;
  left: 3px;
  width: 16px;
  /* Stops short of the last row's bottom rule so the stroke ends on step four
     rather than running past it into the next section's edge. */
  height: calc(100% - 64px);
}

.tl-draw--thread path {
  stroke: var(--ink);
  stroke-width: 1.5;
}

/* The nodes sit on the thread, so they need to be above it and to carry the
   band's own ground, or the stroke shows through the dotted step-four mark. */
.tl-step-stub {
  position: relative;
  z-index: 1;
}

.tl-step-node {
  box-shadow: 0 0 0 5px var(--ground);
}

.tl-stratum--deep .tl-step-node {
  box-shadow: 0 0 0 5px var(--ground-deep);
}

/* At --stub: 0 the stub column collapses onto the body text and there is no
   gutter left to run a thread down. */
@media (max-width: 767px) {
  .tl-draw--thread {
    display: none;
  }
}

/*
 * Scripting on and motion allowed: the stroke is held back at full length and
 * released when it is scrolled to. Every other state — no scripting, reduced
 * motion, the observer never firing — renders it complete, because a flourish
 * that never arrives is just a missing stroke.
 */
.tl-js .tl-draw path {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}

.tl-js .tl-draw.is-drawn path {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 520ms cubic-bezier(0.33, 0.9, 0.35, 1);
}

.tl-js .tl-draw.is-drawn path:nth-child(2) {
  transition-delay: 130ms;
}

.tl-js .tl-draw--thread.is-drawn path {
  transition-duration: 900ms;
}

@media (prefers-reduced-motion: reduce) {
  .tl-js .tl-draw path {
    stroke-dashoffset: 0;
  }
}

/* -------------------------------------------------------- the seeded Q1 -- */
/*
 * The fold's conversion device. A real assessment question, not a fake progress
 * trick: answering it writes the answer and opens the form at question two.
 */

.tl-seed {
  width: 100%;
  max-width: 520px;
}

.tl-seed-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin-top: 10px;
}

/* ------------------------------------------------ buttons — CARVE-OUT --- */
/*
 * Interactive controls sit outside the certainty system. They never carry
 * hatch, dotted or dashed strokes; their hierarchy comes from size, position,
 * accent and left-edge rule weight — never from fill-vs-outline as meaning.
 */

.tl-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 56px;
  padding: 0 24px;
  border: 0;
  border-radius: 2px;
  background: transparent;
  color: var(--ink);
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 100%;
  font-size: 1.0625rem;
  letter-spacing: 0;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 90ms linear, border-color 90ms linear,
    color 90ms linear;
}

.tl-btn--primary {
  background: var(--signal);
  color: var(--signal-on);
}

.tl-btn--primary:hover {
  background: var(--signal-deep);
}

/* No left border: the hours tab supplies that edge, so the button carries one
   left edge rather than a 1.5px border, a 3px tab and 5px of gap between them. */
.tl-btn--secondary {
  border: 1.5px solid var(--ink);
  border-left: 0;
  padding-left: 26px;
}

.tl-btn--secondary:hover {
  border-color: var(--ink-2);
  background: var(--plane);
}

.tl-btn:disabled {
  cursor: not-allowed;
  opacity: 0.55;
}

.tl-btn-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 12px;
  width: 100%;
}

.tl-btn-stack {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/*
 * The stack has no width of its own, so it shrink-wraps to its widest child —
 * the 34ch caption — and a `width: 100%` button inside would resolve against
 * that accidental box and come out wider than the primary slab beside it. The
 * button sizes to its own label instead and the caption wraps under it. At
 * 767 and below `.tl-btn-row .tl-btn { width: 100% }` overrides this, later in
 * the file and at equal specificity, which is what the stacked fold wants.
 */
.tl-btn-stack > .tl-btn {
  width: max-content;
  max-width: 100%;
}

/*
 * The hours indicator: a solid tab that IS the secondary CTA's left edge, not a
 * line beside it. It is a live-state control, so only its VALUE changes, never
 * its material.
 */
.tl-hours-tab {
  position: absolute;
  inset: 0 auto 0 0;
  width: 5px;
  background: var(--rule);
}

/* Overhangs by the border width at both ends so it meets the outer corners of
   the top and bottom borders rather than stopping inside them. */
.tl-btn--secondary .tl-hours-tab {
  inset: -1.5px auto -1.5px 0;
}

:root[data-hours='open'] .tl-hours-tab {
  background: var(--signal);
}

/* The document ships data-hours="unknown" and attribution.js resolves it on
   load. Stated explicitly so the staffed-hours use of the accent — "an agent is
   at the desk right now" — can never be asserted by first paint, or permanently
   with scripting blocked, before anything has actually checked the clock. */
:root[data-hours='unknown'] .tl-hours-tab {
  background: var(--rule);
}

.tl-hours-caption {
  font-size: 0.9375rem;
  line-height: 1.4;
  color: var(--ink-2);
  max-width: 34ch;
}

/* --------------------------------------------------------- figure panel -- */

.tl-fig {
  position: relative;
  border: 1px solid var(--rule);
  background: var(--ground);
  padding: 20px;
}

.tl-fig svg {
  width: 100%;
  height: auto;
}

/*
 * The figure's own sentence, and the only one that says what the marks mean
 * rather than modifying them. It brackets the drawing against .tl-fig-keys
 * below — same rule, same 16px — so caption and key read as one pair of
 * margins around the drawing. It renders at every width; the key does not
 * replace it, because the key names the marks and this names the argument.
 */
.tl-fig-caption {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--rule);
}

/* An outlined chip — solid stroke, because it is a statement about the page,
   not a non-guaranteed value. No accent touches the diagram. One line, and it
   closes the panel: four negations at the top of the column classified the
   whole figure as disclosure furniture before anyone read the drawing. */
.tl-fig-stamp {
  display: inline-block;
  margin: 16px 0 0;
  border: 1.25px solid var(--ink);
  padding: 5px 9px;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 87%;
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
  line-height: 1.3;
  max-width: 56ch;
}

/* The panel's two-chip legend is gone. It predates .tl-fig-keys rendering at
   every width, and once the key prints a swatch and a gloss for all five marks
   the chips repeated two of those words about 50px below them. Two statements
   of the same thing in one panel is the reader's problem, not the page's. */

/* ---- the drawing itself ------------------------------------------------
   No accent colour touches this diagram. The one place a reader could
   mistake colour for meaning is the one place colour is banned. */

.tl-svg-floor {
  fill: var(--mark-g);
}

/* The index is an observable, never a promise — so it is never solid. 1.5 is
   the ceiling for this stroke: any thicker against a `2 3` dash and the dots
   start touching, which would read as solid and collapse the distinction the
   whole system rests on. Widen the dasharray before widening the stroke. */
.tl-svg-idx {
  fill: none;
  stroke: var(--mark-n);
  stroke-width: 1.5;
  stroke-dasharray: 2 3;
}

/* A real event of an unpromised size. It takes the index outline's own x and
   width, so no stroke of its own: the dotted rect drawn over it supplies the
   edge, and the mark is hatch inside a dotted outline — the same object the
   key swatch shows. A solid outline here made the two disagree. */
.tl-svg-credit {
  fill: url(#tl-hatch);
  stroke: none;
}

.tl-svg-hatchline {
  stroke: var(--mark-n);
  stroke-width: 1.5;
}

/* Dotted = never promised. Dashed = a number the carrier can reset. */
.tl-svg-cap {
  stroke: var(--mark-n);
  stroke-width: 1.5;
  stroke-dasharray: 5 4;
  fill: none;
}

/*
 * Label furniture, not a mark. It carries no quantity of its own — it points a
 * stub label at a gap — but at 1.5px in --mark-n it was drawn in the
 * non-guaranteed MATERIAL token, at the weight of the cap and the index, and it
 * was the only unbroken stroke in the drawing besides the floor. The floor has
 * to be the one solid object here, because "solid" is the whole of this page's
 * promise vocabulary.
 *
 * Not --rule: that is the structural hairline and it reaches only 2.1:1 on the
 * figure's ground, below the 3:1 a graphic needs to be understood by. Dashing
 * it is worse than either, because dashed is a material and this is not making
 * a claim. --rule-control exists for exactly this — 3.8:1 light, 6.6:1 dark,
 * and it is the token buttons and field wells use, which are the other things
 * on this page that sit outside the certainty system.
 */
.tl-svg-bracket {
  fill: none;
  stroke: var(--rule-control);
  stroke-width: 1;
}

/*
 * Set in viewBox units, so the rendered size is this number times the SVG's
 * width over 540. At 17 that is 15.7px from 1280 up and 12.9px at 1024; at the
 * 13 it used to carry it was 9.8px and 8.1px — the drawing legible and the
 * words attached to it not. The stub is 158 units wide and the longest string
 * needs 152 of them, so these two sizes are the ceiling, not a preference.
 */
.tl-svg-label {
  fill: var(--ink);
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 17px;
  font-weight: 600;
  font-stretch: 87%;
  letter-spacing: 0.08em;
}

.tl-svg-label--end {
  text-anchor: end;
}

/* The qualifier under each stub label. Never dimmer than the secondary ink and
   never far off the claim's size — this tier carries IN THE CONTRACT and CAN
   CHANGE at the same weight, so it must not be readable as a volume ranking of
   the two. */
.tl-svg-label--sub {
  fill: var(--ink-2);
  font-size: 15px;
  font-weight: 500;
}

/*
 * The Spanish figure is drawn on a 580-unit viewBox against the English 540,
 * so the same rendered box scales its units down by a further 8% and the same
 * font-size lands smaller on screen. It is set larger here to render at parity
 * — 15.5px against English's 15.7px at the width the hero settles at.
 *
 * The stub is still 158 units on both, so the two longest Spanish strings were
 * the binding constraint rather than the type size: at this size the old
 * PERIODOS A LA BAJA and NO SE ACREDITA NADA ran past the left edge. They are
 * now A LA BAJA and NADA ACREDITADO, which say the same thing and fit. Anything
 * longer than about 14 characters will clip here — check it against the render,
 * not against the English string.
 */
[lang='es'] .tl-svg-label {
  font-size: 18px;
}

[lang='es'] .tl-svg-label--sub {
  font-size: 16px;
}

.tl-fig-keys {
  display: grid;
  margin: 0;
  padding: 16px 0 0;
  border-top: 1px solid var(--rule);
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
}

.tl-fig-keys > div {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr);
  gap: 12px;
  align-items: center;
}

.tl-fig-keys dt {
  height: 14px;
  align-self: center;
}

.tl-fig-keys dd {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.4;
  color: var(--ink);
}

.tl-fig-keys dd span {
  display: block;
  color: var(--ink-2);
  font-size: 0.875rem;
}

.tl-fig-key--floor {
  background: var(--mark-g);
}

.tl-fig-key--cap {
  border-top: 1.5px dashed var(--mark-n);
  height: 0 !important;
}

.tl-fig-key--part,
.tl-fig-key--down {
  background: repeating-linear-gradient(
    45deg,
    transparent 0 2.5px,
    var(--mark-n) 2.5px 4px
  );
  border: 1.25px dotted var(--mark-n);
}

/* Empty, with the floor closing it off above — which is what the drawing shows
   in a down period. Without that solid edge this swatch is pixel-identical to
   the six index outlines drawn above the floor, i.e. to the opposite claim. */
.tl-fig-key--down {
  background: none;
  border-top: 3px solid var(--mark-g);
}

/*
 * Projections arrive; guarantees do not. Only the non-guaranteed elements
 * fade in — the floor was already drawn. Gated on .tl-js so that with
 * scripting off the diagram renders complete rather than losing exactly the
 * marks a reader most needs to see.
 */
.tl-js .tl-ng-fade {
  opacity: 0;
  transition: opacity 120ms linear;
}

.tl-js .tl-ng-fade.is-revealed {
  opacity: 1;
}

/* The single highest-credibility sentence on the page. Never demoted. */
.tl-concession {
  margin: 0;
  font-size: 1.09375rem;
  line-height: 1.65;
  font-weight: 600;
  color: var(--ink);
  max-width: 62ch;
  border-left: 1px solid var(--ink);
  padding-left: 20px;
}

/* ------------------------------------------- crediting mechanics rows --- */

.tl-mech {
  display: grid;
  gap: 0;
  margin: 0;
  border-top: 1px solid var(--rule);
}

.tl-mech-row {
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr);
  gap: var(--gutter);
  align-items: start;
  padding-block: 24px;
  border-bottom: 1px solid var(--rule);
}

.tl-mech-fig {
  height: 40px;
  display: flex;
  align-items: center;
}

/* FLOOR: the only solid mass. */
.tl-mech-floor {
  width: 100%;
  height: 14px;
  background: var(--mark-g);
  box-shadow: var(--cast);
}

/* CAP: a number the carrier sets and can reset — dashed, not dotted. */
.tl-mech-cap {
  width: 100%;
  height: 0;
  border-top: 1.5px dashed var(--mark-n);
}

/* PARTICIPATION: a share of the move is credited, not all of it — so this is
   the drawing's own bar-inside-its-outline at 34px, dotted rectangle for the
   index move and hatch for the part of it credited. It used to be a clip-path
   trapezoid rising left to right, which says nothing about a share and is the
   mirror image of the loan wedge. These three rows exist to rescue a reader who
   did not parse the SVG; handing that reader a fourth shape is the one thing
   they cannot afford. */
.tl-mech-part {
  width: 100%;
  height: 34px;
  background: repeating-linear-gradient(
    45deg,
    transparent 0 2.5px,
    var(--mark-n) 2.5px 4px
  );
  background-size: 100% 60%;
  background-position: bottom;
  background-repeat: no-repeat;
  border: 1.25px dotted var(--mark-n);
}

.tl-mech-row dt {
  margin: 0;
}

.tl-mech-row dd {
  margin: 0;
}

/* -------------------------------------------------------------- lattice -- */

.tl-lattice {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border-top: 1px solid var(--rule);
  border-left: 1px solid var(--rule);
}

.tl-lattice-cell {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 32px 28px 36px;
  border-right: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

.tl-lattice-cell h3 {
  margin: 0;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 112%;
  font-size: 1.375rem;
  line-height: 1.2;
  letter-spacing: -0.008em;
  text-wrap: balance;
}

.tl-lattice-cell p {
  margin: 0;
  font-size: 1.0625rem;
  line-height: 1.6;
  color: var(--ink-2);
}

/* ---------------------------------------------------------- proof band --- */

.tl-proof {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 48px var(--gutter);
}

/* An exact grid, not a wrapping row. Six slots of unequal label width wrapped
   4+2 at desktop, 3+3 at 1024 and 5+1 at 768 — the only ragged block on a page
   built entirely from exact grids, sitting in the band a sceptic scans hardest,
   where a half-empty row reads as an unfinished affiliate page. */
.tl-slotrow {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/*
 * A neutral slot awaiting real, verified content. Deliberately plain — it takes
 * no material from the certainty vocabulary, because "not filled in yet" is
 * not a claim about a policy.
 */
.tl-slot {
  border: 1px solid var(--rule);
  padding: 10px 14px;
  color: var(--ink-2);
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 500;
  font-stretch: 87%;
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.3;
}

/*
 * A carrier mark. These are third-party trademarks and the only artwork on the
 * page the agency does not own, so they get a plate of their own rather than
 * being dropped onto the ground colour.
 *
 * The plate is LIGHT in both themes. Every mark here is dark-on-transparent, so
 * on the dark theme's #0d1110 ground an unaltered logo is invisible, and the
 * hover state the greyscale exists to reward would reveal nothing. Lighting the
 * plate rather than filtering the mark is also the safer answer to carrier brand
 * guidelines: hue, proportion and clear space are never touched. It follows the
 * page's own dark rule — a lifted plane is lighter than ground, because the
 * light still comes from above — just carried further than the UI planes are.
 */
.tl-slot--mark {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px 18px;
  min-height: 66px;
  background: var(--mark-plate);
}

/*
 * Height-normalised, not width-normalised: these are six marks of wildly
 * different proportion — wordmarks up to 5.8:1 beside a square emblem — and
 * fitting them to a common width would print the emblem at a fifth of the
 * wordmarks' size. `--mark-h` lets a square mark take more height so it carries
 * the same optical weight; the wordmarks all sit at the 26px default.
 */
.tl-slot--mark img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: var(--mark-h, 26px);
  /*
   * Desaturated at rest so six brand palettes cannot become a seventh voice on
   * a page whose accent has exactly four permitted uses. Colour on hover, which
   * is one of the six state changes in the motion budget.
   *
   * Desaturation is an alteration of the mark and many carrier marketing
   * agreements forbid it; the operator confirmed permission from each of the
   * six on 2026-07-26. If a carrier is added or an agreement is renegotiated,
   * that permission has to be re-confirmed — or drop `filter` for that one
   * mark, since the plate carries it either way.
   */
  filter: grayscale(1);
  transition: filter 160ms ease;
}

/* Guarded: on a touch device :hover can stick after a tap, which would leave
   one mark in colour and five grey for the rest of the visit. */
@media (hover: hover) {
  .tl-slot--mark:hover img,
  .tl-slot--mark:focus-within img {
    filter: grayscale(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .tl-slot--mark img {
    transition: none;
  }
}

/*
 * Reserved, currently unused. The named-agent cards and the review lines were
 * both removed from the proof band rather than shipped with invented content —
 * a fabricated licence number or testimonial is a regulatory problem, not a
 * copy one. These two rules stay so that restoring either block with real,
 * verifiable content is a markup change and nothing else.
 */
.tl-agent-credential {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 16px 0;
  border-top: 1px solid var(--rule);
}

.tl-agent-credential b {
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 100%;
  font-size: 1.0625rem;
}

.tl-review-line {
  margin: 0;
  font-size: 1.09375rem;
  line-height: 1.6;
  max-width: 46ch;
}

.tl-review-line cite {
  display: block;
  margin-top: 6px;
  font-style: normal;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 87%;
  font-size: 0.78125rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
}

/* ----------------------------------------------------------------- form -- */

.tl-form-wrap {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
  gap: 64px;
  align-items: start;
}

.tl-fit {
  max-width: 620px;
}

/* Progress is expressed as RULE WEIGHT, never as squares filling — filling
   would borrow the guaranteed material for something that is not a claim. */
.tl-fit-progress {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 6px;
  margin: 10px 0 28px;
  padding: 0;
  list-style: none;
}

/* --rule is the structural hairline and its own comment says it must not carry
   state; --rule-control is the token that clears 3:1 for exactly this. */
.tl-fit-segment {
  height: 2px;
  background: var(--rule-control);
  align-self: end;
}

/*
 * Position is the rule's WEIGHT — done and current used to resolve to identical
 * CSS, which left the whole burden of "you are here" on a 4px pseudo-element
 * that read as a speck. Bottom-aligned, so the current segment grows upward
 * against a common baseline rather than shifting the row.
 */
.tl-fit-segment.is-done {
  background: var(--ink);
}

.tl-fit-segment.is-current {
  height: 4px;
  background: var(--ink);
}

/*
 * Stepping is progressive enhancement. With scripting off every question is
 * present and the form is one honest scroll; with scripting on only the active
 * step renders, and it never flashes because .tl-js is set in <head>.
 */
.tl-fit-step + .tl-fit-step {
  margin-top: 44px;
  padding-top: 36px;
  border-top: 1px solid var(--rule);
}

.tl-js .tl-fit-step {
  display: none;
}

.tl-js .tl-fit-step.is-active {
  display: block;
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

.tl-js-only {
  display: none;
}

.tl-js .tl-js-only {
  display: block;
}

.tl-js .tl-fit-progress.tl-js-only {
  display: grid;
}

.tl-js .tl-fit-nav.tl-js-only {
  display: flex;
}

/* The head's <noscript> already hides the whole form, so nothing carrying this
   is reachable without scripting. It stays as the second layer: the controls it
   covers are the stepper's Continue buttons and the submit, and every one of
   them is a dead end or a data loss if the form is ever shown unscripted again. */
.tl-no-js-hide {
  display: none;
}

.tl-js .tl-no-js-hide {
  display: inline-flex;
}

.tl-fit-question {
  margin: 0 0 6px;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 100%;
  font-size: 1.5rem;
  line-height: 1.25;
  letter-spacing: -0.005em;
  text-wrap: balance;
}

.tl-fit-help {
  margin: 0 0 20px;
  font-size: 1rem;
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 56ch;
}

/*
 * The hero's age question is answered before the form opens, so a seeded
 * visitor arrives at question two having apparently done nothing. This reports
 * what was banked, set at help-text weight rather than question weight: it is a
 * receipt for a tap that already happened, not another thing to answer.
 */
.tl-fit-answered {
  margin: 0 0 20px;
  font-size: 1rem;
  line-height: 1.55;
  color: var(--ink-2);
}

.tl-fit-answered b {
  font-weight: 600;
  color: var(--ink);
}

.tl-fit-options {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/*
 * Option cards. Selection is a 4px solid LEFT EDGE, never a fill change —
 * controls do not participate in the certainty vocabulary.
 *
 * Each card is a <label> for a radio the browser owns. The input is clipped
 * rather than display:none so it stays focusable and stays IN the group: arrow
 * keys walk the options, the whole question is one tab stop, and "3 of 6" is
 * spoken by the browser instead of being rebuilt out of aria-pressed toggles
 * that announced the wrong pattern anyway. It is also what makes the questions
 * answerable with scripting off, which is the state the README claims and the
 * page did not ship.
 */
.tl-fit-radio {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* The input carries the focus, the label carries the ring. */
.tl-fit-radio:focus-visible + .tl-fit-option {
  outline: 2px solid var(--focus-a);
  outline-offset: 2px;
  box-shadow: 0 0 0 3px var(--focus-b);
}

.tl-fit-option {
  position: relative;
  display: block;
  width: 100%;
  min-height: 56px;
  padding: 12px 18px 12px 22px;
  text-align: left;
  background: var(--plane);
  border: 1px solid var(--rule-control);
  border-left: 4px solid transparent;
  cursor: pointer;
  transition: border-color 90ms linear, background-color 90ms linear;
}

.tl-fit-option:hover {
  border-color: var(--ink-2);
  border-left-color: var(--rule-control);
}

/* Two selectors for one state: :checked is the English page's radio cards,
   .is-selected is the aria-pressed buttons es/index.html still ships. Both
   shapes are handled here and in fit-form.js until the Spanish form is
   mirrored — a Spanish visitor cannot be left with six dead questions. */
.tl-fit-option.is-selected,
.tl-fit-radio:checked + .tl-fit-option {
  border: 1.5px solid var(--ink);
  border-left: 4px solid var(--ink);
}

.tl-fit-option b {
  display: block;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 500;
  font-stretch: 100%;
  font-size: 1.0625rem;
  line-height: 1.35;
}

.tl-fit-option.is-selected b,
.tl-fit-radio:checked + .tl-fit-option b {
  font-weight: 600;
}

.tl-fit-option small {
  display: block;
  margin-top: 2px;
  font-size: 0.9375rem;
  line-height: 1.45;
  color: var(--ink-2);
}

/*
 * The counter and Back on one line. Back used to sit after the seventh
 * fieldset, outside every step, so on a phone it was below the whole active
 * question — off screen for the length of Q3 — while an option advances 220ms
 * after a tap. The undo has to be visible from where the tap happened.
 */
.tl-fit-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  /* Back is absent on step one and present on every step after it, so the row
     has to reserve the taller of the two states or the counter drops 25px at
     the exact moment the visitor answers question one. This is the Back
     control's own height: 12 + 12 of padding around 13.5px at 1.4. */
  min-height: 43px;
}

.tl-fit-head .tl-micro {
  margin: 0;
}

/* The base rule is still the standalone nav the Spanish page carries at the
   foot of its form, which needs its own clearance from the step above. */
.tl-fit-nav {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-top: 24px;
  flex-wrap: wrap;
}

.tl-fit-head .tl-fit-nav {
  gap: 0;
  margin-top: 0;
}

/* Punctuation. Two runs of uppercase Archivo at 13.5px sitting side by side
   read as one string without it. Scoped to the counter line: the Spanish page
   still carries its nav at the foot of the form, where a lone middot floating
   above BACK would be debris. */
.tl-fit-head .tl-fit-nav::before {
  content: '\00B7';
  color: var(--ink-2);
}

/* .tl-js-only is display:none at equal specificity and earlier in the file, so
   both rules above beat it and Back rendered without scripting — a dead control
   beside a form that is one honest scroll and has no steps to go back through.
   Stated as its own rule rather than by reordering, because the nav's layout and
   the nav's existence are two different questions. */
html:not(.tl-js) .tl-fit-nav,
html:not(.tl-js) .tl-fit-head {
  display: none;
}

.tl-back {
  background: none;
  border: 0;
  padding: 8px 0;
  cursor: pointer;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 87%;
  font-size: 0.84375rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
  text-decoration: underline;
  text-underline-offset: 4px;
}

.tl-back:hover {
  color: var(--ink);
}

/* The nav copy is a primary escape hatch on a phone and 40x32 is not a target;
   the padding is the whole of the fix, since the glyph is 13.5px of uppercase.
   Scoped, because the other .tl-back is the "Change" control inside the
   answered line, where it sits mid-sentence and must stay inline-sized. */
.tl-fit-nav .tl-back {
  padding: 12px;
  line-height: 1.4;
}

/* Recessed wells read as "write here" — they beat flat-bordered and
   underline-only fields on mobile tap-affordance. */
.tl-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 18px;
}

.tl-field-well {
  width: 100%;
  min-height: 56px;
  padding: 14px 16px;
  background: var(--ground-deep);
  border: 1px solid var(--rule-control);
  border-left: 4px solid transparent;
  box-shadow: var(--cast-inset);
  color: var(--ink);
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-stretch: 100%;
  font-size: 1.0625rem;
}

select.tl-field-well {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink) 50%),
    linear-gradient(135deg, var(--ink) 50%, transparent 50%);
  background-position: calc(100% - 22px) calc(50% + 2px),
    calc(100% - 16px) calc(50% + 2px);
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  padding-right: 44px;
}

/*
 * An invalid field is not a non-guaranteed claim, so an error state may never
 * borrow dotted, dashed or hatched material — and it is not the accent either,
 * because --signal has an enumerated list of permitted uses and this is not on
 * it. Validation gets its own semantic token.
 */
.tl-field-well[aria-invalid='true'] {
  border-color: var(--alert);
  border-width: 1.5px;
  border-left: 4px solid var(--alert);
}

/* The same treatment as the label above the field it belongs to. In the body
   serif at weight 600 these were the heaviest text on the page — four bold
   Literata blocks down the final step, out-weighing the question set in Archivo
   above them, in an ink identical to --ink. It read as being told off. */
.tl-field-error {
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-stretch: 87%;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--alert-ink);
  font-weight: 600;
}

.tl-field-error:empty {
  display: none;
}

/*
 * The plain-language line above the disclosure. Archivo rather than the label's
 * Literata, so it reads as the page speaking rather than as a second paragraph
 * of the agreement, and at full ink because it is not fine print. It sits
 * OUTSIDE #tl-consent-text: that element is snapshotted verbatim on to the
 * lead, and it is the disclosure, not this.
 */
.tl-consent-summary {
  margin: 0 0 10px;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 100%;
  font-size: 0.9375rem;
  line-height: 1.5;
  max-width: 62ch;
}

.tl-consent {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  gap: 14px;
  align-items: start;
  padding: 16px;
  margin: 8px 0 20px;
  background: var(--ground-deep);
  border: 1px solid var(--rule);
}

.tl-consent-box {
  width: 24px;
  height: 24px;
  margin: 2px 0 0;
  appearance: none;
  background: var(--plane);
  border: 1.5px solid var(--ink);
  cursor: pointer;
  flex: none;
}

.tl-consent-box:checked {
  background: var(--ink);
}

.tl-consent-box:checked::after {
  content: '';
  display: block;
  width: 11px;
  height: 6px;
  margin: 5px auto 0;
  border-left: 2px solid var(--plane);
  border-bottom: 2px solid var(--plane);
  transform: rotate(-45deg);
}

.tl-consent label {
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--ink-2);
  cursor: pointer;
}

/* Second row of the consent grid, under the disclosure rather than under the
   24px checkbox column. */
.tl-consent .tl-field-error {
  grid-column: 2;
  margin: 12px 0 0;
}

/*
 * The consent checkbox is the one control that blocks every submission, and it
 * is 24px of control inside a block the height of a phone screen. "Check the
 * highlighted fields" has to highlight something findable, so the block takes
 * the same 1.5px + 4px --alert edge the wells take. Still not the accent, and
 * still not a certainty material: validation is not a claim about a policy.
 */
.tl-consent[data-invalid='true'] {
  border: 1.5px solid var(--alert);
  border-left: 4px solid var(--alert);
}

/* The same, for anything that marks the box invalid without going through
   setError. It sits in its own rule on purpose: a browser that does not know
   :has() throws out the whole selector list it appears in, and it would take
   the attribute rule above with it. */
.tl-consent:has(.tl-consent-box[aria-invalid='true']) {
  border: 1.5px solid var(--alert);
  border-left: 4px solid var(--alert);
}

.tl-consent-box[aria-invalid='true'] {
  border-color: var(--alert);
}

/*
 * Live state of the consent box, rendered beside the button it gates because
 * the box itself is a screen-height away by the time the thumb reaches the
 * submit. It reports the state of a control, so it takes neither the accent nor
 * any certainty material — the difference between the two states is the words.
 */
.tl-consent-state {
  margin: 0 0 10px;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 87%;
  font-size: 0.9375rem;
  line-height: 1.4;
  color: var(--ink-2);
}

.tl-consent-state[data-given='true'] {
  color: var(--ink);
}

/*
 * A called-out message, not a control. Filled and boxed at full field width
 * directly above the submit, and set in the reading face, it read as an empty
 * text field the visitor had failed to complete — a fourth thing to do on a
 * step that was already asking for three. The fill and the box go; what is left
 * is a hard left edge and the interface face, which is the same grammar
 * .tl-concession uses to lift one sentence out of a column.
 */
.tl-status {
  margin: 16px 0 0;
  padding: 2px 0 2px 16px;
  border-left: 3px solid var(--ink);
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-stretch: 87%;
  font-size: 1rem;
  line-height: 1.5;
}

/* The form's own live region carries nothing but failures — a blocked submit or
   a send that did not go — so it takes the validation token the field errors
   take. Every other .tl-status on the site is telling the visitor something,
   not telling them something went wrong. */
#tl-status {
  border-left-color: var(--alert);
}

.tl-status:empty {
  display: none;
}

/* ------------------------------------------------------------ how it works -- */

.tl-steps {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--rule);
}

.tl-step {
  display: grid;
  grid-template-columns: var(--stub) minmax(0, 1fr);
  gap: var(--gutter);
  padding-block: 32px;
  border-bottom: 1px solid var(--rule);
}

/* Start, not stretch. The stub is a grid child of a ~200px row, so it used to
   fill the row and the node, centred inside it, dropped 53px below the numeral
   it belongs to — four squares stranded in the left gutter beside the second
   line of each paragraph. */
.tl-step-stub {
  display: flex;
  align-items: baseline;
  align-self: start;
  gap: 14px;
}

/* An empty span's baseline is its bottom edge, so baseline alignment sits the
   node on the numeral's baseline rather than on its cap line. */
.tl-step-node {
  width: 14px;
  height: 14px;
  flex: none;
  background: var(--mark-g);
  transform: translateY(-4px);
}

/* "We'll tell you if IUL is the wrong fit" is a promise about character, not a
   contract term. It gets the non-guaranteed material — but hatched, not empty.
   An unfilled dotted rectangle is already a defined object on this page:
   .tl-fig-key--down uses exactly that object for "Down periods, nothing
   credited", so anyone who decoded the hero key read step four as "nothing
   happens here". Sixteen rather than fourteen so the pitch resolves. */
.tl-step-node--n {
  width: 16px;
  height: 16px;
  background: repeating-linear-gradient(
    45deg,
    transparent 0 2.5px,
    var(--mark-n) 2.5px 4px
  );
  border: 1.5px dotted var(--mark-n);
}

.tl-step-body h3 {
  margin: 0 0 8px;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 112%;
  font-size: 1.375rem;
  line-height: 1.2;
  letter-spacing: -0.008em;
  text-wrap: balance;
}

.tl-step-body p {
  margin: 0;
  max-width: 58ch;
  color: var(--ink-2);
}

/* ------------------------------------------------------------------ faq -- */

.tl-faq {
  border-top: 1px solid var(--rule);
}

/* Every rule here is neutral. The row dividers used to restate the row's
   certainty class in rule weight — but the two BOTH rows both took the solid
   guaranteed rule for want of a split treatment, the rules landed on the same
   pixels as the previous row's border, and the footer key has no entry for a
   horizontal divider in any material. A divider is structure, not content; the
   chip beside the question is what classifies the row. */
.tl-faq-row {
  border-bottom: 1px solid var(--rule);
}

.tl-faq-q {
  display: grid;
  grid-template-columns: var(--stub) minmax(0, 1fr) 28px;
  gap: var(--gutter);
  align-items: start;
  width: 100%;
  padding: 22px 0;
  background: none;
  border: 0;
  text-align: left;
  cursor: pointer;
  color: inherit;
}

.tl-faq-h {
  margin: 0;
  font: inherit;
}

.tl-faq-q .tl-faq-text {
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 100%;
  font-size: 1.1875rem;
  line-height: 1.35;
  letter-spacing: -0.005em;
}

.tl-faq-marker {
  position: relative;
  width: 16px;
  height: 16px;
  margin-top: 5px;
  justify-self: end;
  flex: none;
}

.tl-faq-marker::before,
.tl-faq-marker::after {
  content: '';
  position: absolute;
  background: var(--ink);
  transition: transform 180ms ease-out;
}

.tl-faq-marker::before {
  inset: 7px 0 7px 0;
  height: 2px;
}

.tl-faq-marker::after {
  inset: 0 7px 0 7px;
  width: 2px;
}

.tl-faq-q[aria-expanded='true'] .tl-faq-marker::after {
  transform: rotate(90deg);
}

/*
 * Collapsing is progressive enhancement like everything else here, and the only
 * thing that can reopen a collapsed answer is script. Ungated, these rules clip
 * all seven answers to nothing for anyone whose JavaScript never arrives — or
 * whose page.js threw before it reached initFaq().
 */
.tl-js .tl-faq-a {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 180ms ease-out;
}

.tl-js .tl-faq-row.is-open .tl-faq-a {
  grid-template-rows: 1fr;
}

.tl-js .tl-faq-a > div {
  overflow: hidden;
  /* Clipping alone keeps the answer in the accessibility tree while
     aria-expanded says false. visibility takes it out, and delaying it to the
     end of the transition keeps the open/close animation intact. */
  visibility: hidden;
  transition: visibility 0s linear 180ms;
}

.tl-js .tl-faq-row.is-open .tl-faq-a > div {
  visibility: visible;
  transition: visibility 0s linear 0s;
}

/* With no script the answers are simply present, so the +/− marker would be
   describing a state that does not exist and the row must not invite a tap
   that cannot do anything. */
html:not(.tl-js) .tl-faq-marker {
  display: none;
}

html:not(.tl-js) .tl-faq-q {
  pointer-events: none;
  cursor: default;
}

.tl-faq-inner {
  display: grid;
  grid-template-columns: var(--stub) minmax(0, 68ch) minmax(0, 1fr);
  gap: var(--gutter);
  padding-bottom: 28px;
}

.tl-faq-inner p {
  grid-column: 2;
  margin: 0;
  color: var(--ink-2);
}

/* A qualifier hanging beside the paragraph it qualifies — a document-native
   device no card layout can borrow. */
.tl-marginalia {
  grid-column: 3;
  margin: 0;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 500;
  font-stretch: 87%;
  font-size: 0.8125rem;
  line-height: 1.45;
  letter-spacing: 0.02em;
  color: var(--ink-2);
  border-top: 1.25px dotted var(--mark-n);
  padding-top: 8px;
}

/* -------------------------------------------------------------- closing -- */

.tl-closing {
  display: flex;
  flex-direction: column;
  align-items: start;
  gap: 24px;
}

/*
 * The one inverted stratum. Its background reads from --terminal-bg, which is
 * NOT redefined here — the descendants' tokens are, so every mark, rule and
 * button inside re-renders correctly against the dark ground.
 */
.tl-stratum--invert {
  background: var(--terminal-bg);
  border-bottom-color: var(--terminal-bg);
  --ground: var(--terminal-bg);
  --ground-deep: var(--terminal-bg);
  --plane: var(--terminal-plane);
  --ink: var(--terminal-ink);
  --ink-2: var(--terminal-ink-2);
  --rule: var(--terminal-rule);
  --mark-g: var(--terminal-ink);
  --mark-n: var(--terminal-mark-n);
  --signal: var(--terminal-signal);
  --signal-deep: var(--terminal-signal-deep);
  --signal-on: var(--terminal-signal-on);
  --focus-a: var(--terminal-ink);
  --focus-b: var(--terminal-bg);
  color: var(--ink);
}

/* --------------------------------------------------------------- footer -- */

.tl-footer-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 40px var(--gutter);
  padding-bottom: 48px;
  border-bottom: 1px solid var(--rule);
}

.tl-footer-block h2 {
  margin: 0 0 12px;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 87%;
  font-size: 0.78125rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.tl-footer-block address {
  font-style: normal;
  font-size: 0.9375rem;
  line-height: 1.7;
}

.tl-footer-links {
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.9375rem;
  line-height: 1.9;
}

/* The key is printed exactly as a carrier illustration prints its legend. */
.tl-key {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 24px var(--gutter);
  margin: 0;
  padding: 40px 0;
  border-bottom: 1px solid var(--rule);
}

.tl-key div {
  display: flex;
  gap: 14px;
  align-items: start;
}

.tl-key dt {
  flex: none;
  width: 44px;
  height: 22px;
  margin-top: 2px;
}

.tl-key dd {
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--ink-2);
}

.tl-key-g {
  background: var(--mark-g);
}

/* All three non-guaranteed materials in the one swatch that names them. The
   dashed edge is the cap, which is the most consequential non-guaranteed
   element on the page and had no entry here at all — leaving it visually
   indistinguishable from the file's many decorative rules. */
.tl-key-n {
  background: repeating-linear-gradient(
    45deg,
    transparent 0 2.5px,
    var(--mark-n) 2.5px 4px
  );
  border: 1.25px dotted var(--mark-n);
  border-top: 1.5px dashed var(--mark-n);
}

/* Stacked, because the sentence beside it says the non-guaranteed part sits
   ABOVE the guaranteed minimum and the drawing stacks. The lattice's own split
   mark stays horizontal — its heading says "side by side". */
.tl-key-split {
  background: linear-gradient(to top, var(--mark-g) 0 50%, transparent 50%),
    repeating-linear-gradient(45deg, transparent 0 2.5px, var(--mark-n) 2.5px 4px);
  border-top: 1.25px dotted var(--mark-n);
}

.tl-key-btn {
  border: 1.5px solid var(--ink);
}

.tl-disclosures {
  display: grid;
  gap: 16px;
  padding: 40px 0 0;
}

/* ------------------------------------------------------- sticky call bar -- */

/*
 * One slab and one line, not two slabs. Side by side at 375px the two buttons
 * were 169px each and BOTH labels wrapped to two lines, which is where a bar
 * that is meant to be one obvious action stops being one. The slab now carries
 * the dialable number, because the header is not sticky and nothing else on
 * screen has a number on it below the fold.
 */
.tl-callbar {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 40;
  display: none;
  flex-wrap: wrap;
  gap: 8px;
  padding: 8px 16px calc(8px + env(safe-area-inset-bottom));
  background: var(--plane);
  border-top: 1px solid var(--rule);
  box-shadow: 0 -1px 0 rgba(23, 28, 26, 0.14);
  opacity: 0;
  /* An opacity-0 element still hit-tests and still takes focus, which would put
     a live tel: link under the bottom 68px of every phone fold. */
  pointer-events: none;
  visibility: hidden;
  transition: opacity 140ms linear, visibility 0s linear 140ms;
}

.tl-callbar.is-shown {
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
  transition: opacity 140ms linear, visibility 0s linear 0s;
}

/* During staffed hours the phone slab is accent-filled, so its live tab has to
   read against the accent rather than disappear into it. */
.tl-callbar .tl-btn--primary .tl-hours-tab {
  background: var(--signal-on);
}

.tl-callbar .tl-btn {
  flex: 1;
  min-height: 52px;
  padding-inline: 12px;
  font-size: 1rem;
}

/*
 * The action the bar is not leading with, one tap away. A link rather than a
 * second slab: two slabs read as a choice, and this is a fallback.
 *
 * Its full-row basis is what turns the bar into a slab-over-line: only one of
 * the two slabs is ever on show, so `flex: 1` gives that one the whole first
 * row and this wraps beneath it. The Spanish bar has no alt line yet and keeps
 * its two-across row untouched.
 */
.tl-callbar-alt {
  flex: 1 0 100%;
  margin: 0;
  text-align: center;
  font-size: 0.9375rem;
  line-height: 1.35;
}

/* --------------------------------------------------------------- focus -- */

:focus-visible {
  outline: 2px solid var(--focus-a);
  outline-offset: 2px;
  box-shadow: 0 0 0 3px var(--focus-b);
  border-radius: 0;
}

/* ----------------------------------------------------------- responsive -- */

@media (max-width: 1023px) {
  :root {
    --stub: 148px;
  }

  /* The panel stops being an overlay and becomes the width of the shell. The
     film still leads; it just gets its own band above rather than behind. */
  .tl-hero-panel {
    max-width: none;
    padding: 30px 28px 34px;
  }

  .tl-hero-inner {
    padding-block: 64px 40px;
  }

  /*
   * Stacked, the figure would take the whole shell — 728px at 834, which sets
   * the in-drawing labels larger than the body copy of the section beneath it
   * and pushes the panel's own key below the fold. Capped at the width the
   * two-column layout gives it at 1024, and centred in the panel.
   */
  .tl-fig svg {
    max-width: 520px;
    margin-inline: auto;
  }

  /* No font-stretch narrowing here. It pulled the headline to wdth 112 while
     every section head below it stayed at 118, so on the one band where the h1
     was already the smaller object it was the narrower one too. */
  .tl-h1 {
    line-height: 1.06;
  }

  .tl-form-wrap {
    grid-template-columns: minmax(0, 1fr);
    gap: 48px;
  }

  .tl-lattice {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .tl-proof {
    grid-template-columns: minmax(0, 1fr);
    gap: 32px;
  }

  .tl-footer-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .tl-faq-inner {
    grid-template-columns: var(--stub) minmax(0, 1fr);
  }

  .tl-marginalia {
    grid-column: 2;
  }
}

@media (max-width: 767px) {
  :root {
    --margin: 20px;
    --stub: 0px;
  }

  /* Both narrow together on a 335px column, and neither carries a size here:
     the two clamps bottom out at 34px and 24px, which is the widest rank the
     pair ever has. Equal width, so the hierarchy is carried by size alone —
     the width axis cannot rank two things when the smaller one is the wider. */
  .tl-h1 {
    font-stretch: 100%;
  }

  .tl-section-head {
    font-stretch: 100%;
  }

  .tl-band {
    padding-block: 56px;
  }

  /*
   * Fold budget on a 375x667 phone: the primary CTA has to be fully visible
   * without scrolling. Everything above it is measured against that.
   */
  .tl-header {
    min-height: 0;
    padding-block: 10px;
    gap: 12px;
  }

  /* The staffed-hours string repeats in the hero caption 300px lower, so the
     header keeps only the wordmark and the number you would actually tap. */
  .tl-header .tl-micro {
    display: none;
  }

  .tl-wordmark {
    font-size: 1.0625rem;
  }

  .tl-wordmark span {
    display: none;
  }

  /*
   * On the narrowest phones the wordmark and the number stop fitting on one
   * row, and the wrap costs ~40px of fold. Shrinking both keeps the header a
   * single line down to 320px, which keeps the primary CTA above the fold.
   */
  @media (max-width: 360px) {
    .tl-wordmark {
      font-size: 0.9375rem;
    }

    .tl-header .tl-tel {
      font-size: 0.9375rem;
    }

    .tl-header {
      gap: 8px;
    }
  }

  /*
   * Phone: the film and the panel stop overlapping and stack. The overlay
   * layout would put the whole panel over the footage on a 375px screen, which
   * leaves the film as a texture behind text rather than something anyone
   * actually sees — the opposite of leading with it.
   *
   * The band is sized so the film, the trust line, the headline and the first
   * answer all land above 667px. The film gets 34vh: enough to read three
   * faces, not so much that it pushes the first question off the fold.
   */
  .tl-hero-film {
    grid-template-areas: 'media' 'panel';
    grid-template-rows: auto auto;
    min-height: 0;
  }

  .tl-hero-media {
    grid-area: media;
    /*
     * The fold budget on a 375x667 phone is the constraint here, not taste.
     * At 34vh the film pushed the primary CTA to 807px — off the fold on the
     * device most of this traffic arrives on. A quarter of the viewport is
     * enough to read three faces and still land the first question.
     */
    height: 24vh;
    min-height: 150px;
    max-height: 200px;
  }

  .tl-hero-inner {
    grid-area: panel;
    padding-block: 0;
    align-items: stretch;
  }

  .tl-hero-panel {
    padding: 20px 0 26px;
    gap: 14px;
    /* Pulled up over the film's bottom edge so the two read as one object
       rather than as a picture with a box under it. */
    margin-top: -24px;
    border-inline: 0;
    /* Negative margins move an element, they do not widen it: width:100%
       resolves against the shell's content box either way, so the panel has to
       be told to take the padding back as width or it sits 40px short. */
    width: calc(100% + var(--margin) * 2);
    margin-inline: calc(var(--margin) * -1);
    padding-inline: var(--margin);
  }

  /*
   * The lead moves below the buttons on a phone. It is the one element in the
   * panel that argues rather than asks, and at 375 it costs four lines between
   * the headline and the first thing a visitor can tap. Reordering is visual
   * only: it is a paragraph, so nothing focusable changes place and the tab
   * order is untouched.
   */
  .tl-hero-panel > .tl-hero-trust { order: 1; }
  .tl-hero-panel > .tl-h1 { order: 2; }
  .tl-hero-panel > .tl-seed { order: 3; }
  .tl-hero-panel > .tl-micro:not(.tl-hero-trust) { order: 4; }
  .tl-hero-panel > .tl-btn-row { order: 5; }
  .tl-hero-panel > .tl-lead { order: 6; }
  .tl-hero-panel > .tl-trust { order: 7; }

  .tl-hero-toggle {
    top: 10px;
    right: 10px;
  }

  .tl-lead {
    font-size: 1.0625rem;
    line-height: 1.5;
  }

  /* One rule down the whole list. Giving each item its own left border drew
     three unconnected ticks in the left margin instead of one list. */
  .tl-trust {
    grid-template-columns: minmax(0, 1fr);
    gap: 6px;
    border-left: 1px solid var(--rule);
  }

  .tl-trust li,
  .tl-trust li:first-child {
    padding-inline: 12px 0;
    border-left: 0;
  }

  .tl-lattice {
    grid-template-columns: minmax(0, 1fr);
  }

  .tl-lattice-cell {
    padding: 26px 0 30px;
    border-right: 0;
  }

  .tl-lattice {
    border-left: 0;
  }

  .tl-seed-row .tl-fit-option {
    padding: 12px 6px;
    text-align: center;
    border-left-width: 1px;
    border-left-color: var(--rule-control);
  }

  .tl-seed-row .tl-fit-option b {
    font-size: 0.9375rem;
  }

  .tl-seed-row .tl-fit-option.is-selected,
  .tl-seed-row .tl-fit-radio:checked + .tl-fit-option {
    border: 1.5px solid var(--ink);
    border-bottom: 4px solid var(--ink);
  }

  /* Two across, still exact. Six slots wrapping is the failure being fixed. */
  .tl-slotrow {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* The caption swaps between three staffed-hours variants of different lengths,
     and the swap lands while the trust list below it is being read. Reserving
     the tallest keeps that list still under the visitor's thumb. Only the gated
     ones swap — the class is also used for the fixed "call us" lines that close
     three content sections, and those would just carry dead space. */
  .tl-hours-caption[data-tl-when] {
    min-height: 4.2em;
  }

  /* Stretch, not the row's default flex-start: without it the primary sizes to
     its own label and the stack to its 34ch caption, so the two CTAs end at
     different x at the very top of the fold. */
  .tl-btn-row {
    flex-direction: column;
    align-items: stretch;
  }

  .tl-btn-row .tl-btn {
    width: 100%;
  }

  .tl-split,
  .tl-step,
  .tl-faq-q {
    grid-template-columns: minmax(0, 1fr);
    gap: 12px;
  }

  /*
   * One track — but the answer paragraphs kept `grid-column: 2` from the desktop
   * three-track layout, which creates an implicit second column and indents
   * every answer to the right of the question that owns it: the only body text
   * on the page off the left margin. row-gap only, so the implicit column can
   * never buy itself a 24px gutter again.
   */
  .tl-faq-inner {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 12px;
  }

  .tl-faq-inner p,
  .tl-faq-inner .tl-marginalia {
    grid-column: 1;
  }

  .tl-faq-q {
    grid-template-columns: minmax(0, 1fr) 28px;
  }

  .tl-faq-q .tl-chip {
    grid-column: 1 / -1;
  }

  .tl-footer-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 32px;
  }

  .tl-mech-row {
    grid-template-columns: minmax(0, 1fr);
    gap: 14px;
  }

  .tl-mech-fig {
    max-width: 120px;
  }

  /* The bar is mobile-only and appears only after the hero has been read. */
  .tl-callbar {
    display: flex;
  }

  /* Border, padding, slab, gap and the alternate line: 1 + 8 + 52 + 8 + 19 + 8.
     The inset is carried too, because the bar adds it to its own padding and
     the page underneath has to clear the whole thing. */
  body.has-callbar {
    padding-bottom: calc(100px + env(safe-area-inset-bottom));
  }

  /* Keep anything scrolled-to — including a keyboard-focused field — clear of
     the fixed bar (WCAG 2.2, focus not obscured). */
  html {
    scroll-padding-bottom: calc(112px + env(safe-area-inset-bottom));
  }

  .tl-fig {
    padding: 16px;
  }

  .tl-concession {
    padding-left: 16px;
  }
}

/*
 * Where the stub labels stop being readable, NOT where the hero stacks — the
 * two used to be the same number by coincidence and the figure lost its words
 * 300px early. Below 768 the shell margin is 20 and the panel padding 16, so
 * the SVG is (viewport - 74) wide and a sub-label renders at 15 x that / 540.
 * At 480 that is a 406px drawing and an 11.3px sub-label; under it the caveats
 * drop below 11px, which is the size this figure was rebuilt to get away from.
 * Every phone in the set is comfortably inside this block; a small laptop
 * window is not, and now keeps the labelled drawing.
 */
@media (max-width: 479px) {
  .tl-svg-label,
  .tl-svg-bracket {
    display: none;
  }

  /*
   * With the stub labels gone their gutter is dead space, so the drawing is
   * scaled up and pulled left to crop it out. The gutter ends at x=144 of 540,
   * so the drawing is 540/396 = 136% wider and shifted left by that share of the
   * viewBox TIMES the scale: 144/540 x 136% = 36.4%.
   */
  .tl-fig {
    overflow: hidden;
  }

  .tl-fig svg {
    width: 136%;
    max-width: none; /* beats the global svg { max-width: 100% } */
    margin-left: -36.4%;
  }

  /* The Spanish figure is drawn on a wider viewBox, so the same gutter is a
     smaller share of it and it needs its own crop: 580/436 = 133% wider,
     shifted 144/580 x 133% = 33%. */
  [lang='es'] .tl-fig svg {
    width: 133%;
    max-width: none;
    margin-left: -33%;
  }
}

@media (min-width: 768px) {
  .tl-callbar {
    display: none !important;
  }

  /* Two columns, because the key is the only gloss PARTICIPATION has and it was
     hidden at exactly the widths where the bracket appears with no explanation.
     Paired up, it also fills the 270-300px of empty panel that a one-column key
     left below the drawing at every desktop width. */
  .tl-fig-keys {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 24px;
  }
}

@media (min-width: 1024px) {
  /*
   * Three to a row, so the headings have to reserve the same height or the row
   * loses its baseline: "non-guaranteed," is a single unbreakable word joined
   * against a hyphen, which takes cell one to three lines while its neighbours
   * set two, and starts its body 26px below theirs. Three lines at the heading's
   * own 1.2 line-height, so nothing is clipped and the bodies line up.
   */
  .tl-lattice-cell h3 {
    min-height: 3.6em;
  }

  /*
   * The form's last step runs to about y2000 while the aside stops near y860,
   * so the consent block, the submit and the reassurance caption are read
   * beside an empty column. Pinned, the agent credential and the "call
   * instead" number stay on screen for the whole of that scroll — which is
   * where someone who balks at the checkbox needs somewhere else to go.
   */
  .tl-form-wrap > .tl-stack {
    position: sticky;
    top: 24px;
    align-self: start;
  }
}

/* ------------------------------------------------------- reduced motion -- */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    transition-duration: 0ms !important;
    animation-duration: 0ms !important;
    animation-iteration-count: 1 !important;
  }

  /* The diagram renders complete, including every non-guaranteed element. */
  .tl-ng-fade {
    opacity: 1 !important;
  }
}

/* -------------------------------------------------------------- utility -- */

.tl-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* For a clause that changes meaning if it is read across a line break. Used on
   the fold's obligation line, where "nothing / is purchased here" spends one eye
   movement asserting the opposite. */
.tl-nowrap {
  white-space: nowrap;
}

.tl-stack {
  display: flex;
  flex-direction: column;
  gap: 20px;
  align-items: start;
}

.tl-stack--wide {
  gap: 32px;
}

.tl-head-group {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-bottom: 40px;
  align-items: start;
}

/* ------------------------------------------------------ document pages -- */
/*
 * Privacy, terms, disclosures and the thank-you page. Same materials, plainer
 * composition: a single measured column on the page ground. These pages carry
 * the content a regulator or a careful reader goes looking for, so they are set
 * to be read rather than to be skimmed past.
 */

.tl-doc {
  max-width: 74ch;
  padding-block: 72px 96px;
}

.tl-doc h1 {
  margin: 0 0 8px;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 118%;
  font-size: clamp(1.9rem, 3.4vw, 2.75rem);
  line-height: 1.08;
  letter-spacing: -0.014em;
  text-wrap: balance;
}

.tl-doc h2 {
  margin: 48px 0 12px;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 112%;
  font-size: 1.375rem;
  line-height: 1.25;
  letter-spacing: -0.008em;
  padding-top: 20px;
  border-top: 1px solid var(--rule);
}

.tl-doc h3 {
  margin: 28px 0 8px;
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 100%;
  font-size: 1.0625rem;
}

.tl-doc p,
.tl-doc li {
  font-size: 1.0625rem;
  line-height: 1.65;
  color: var(--ink-2);
}

.tl-doc p {
  margin: 0 0 16px;
}

.tl-doc ul,
.tl-doc ol {
  margin: 0 0 16px;
  padding-left: 22px;
}

.tl-doc li {
  margin-bottom: 8px;
}

.tl-doc strong {
  color: var(--ink);
}

.tl-doc a {
  color: var(--ink);
  text-underline-offset: 3px;
}

/* A button inside a document column is still a button. The rule above is one
   specificity step above .tl-btn--primary, so it was repainting the accent
   slab's label to --ink: near-black on brick, 2.29:1, on the only CTA the
   thank-you pages carry. */
.tl-doc a.tl-btn {
  color: var(--ink);
  text-decoration: none;
}

.tl-doc a.tl-btn--primary {
  color: var(--signal-on);
}

.tl-updated {
  margin: 0 0 40px;
}

/* The thank-you page's one job is telling someone exactly what happens next. */
.tl-next {
  margin: 32px 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--rule);
}

.tl-next li {
  display: grid;
  grid-template-columns: 14px minmax(0, 1fr);
  gap: 16px;
  align-items: start;
  padding: 20px 0;
  margin: 0;
  border-bottom: 1px solid var(--rule);
  color: var(--ink);
}

.tl-next li::before {
  content: '';
  width: 14px;
  height: 14px;
  margin-top: 6px;
  background: var(--mark-g);
}

/* The one step nobody can promise: it depends on when you sent this. */
.tl-next li.is-conditional::before {
  background: none;
  border: 1.5px dotted var(--mark-n);
}

/* ------------------------------------------------------------- imagery -- */
/*
 * Photography lives in the same material world as everything else: hard 1px
 * edge, zero radius, no blurred shadow, no vignette, no rounded corner. The
 * grade pulls a warm stock frame toward the limestone palette so it reads as
 * part of the page rather than pasted onto it — restrained on purpose, because
 * a heavy duotone on a family photograph looks like it is trying to hide that
 * it is a stock photograph.
 *
 * Photographs carry NO certainty material. They are not marks, they make no
 * claim about a policy, and the filled/dotted vocabulary never touches them.
 */

.tl-figure {
  position: relative;
  margin: 0;
  border: 1px solid var(--rule);
  background: var(--ground-deep);
  overflow: hidden;
}

.tl-figure img {
  display: block;
  width: 100%;
  height: auto;
  filter: var(--img-filter);
}

/*
 * The form rail's photograph. At 4:5 it is a ~470px block injected between
 * question one and the credential paragraph on a phone — the loudest thing in
 * the column, and a licensed stock frame. Cropped it is ~235px: still present,
 * no longer the argument. 25% down the frame keeps the desk and the hands and
 * loses most of the ceiling.
 */
.tl-agent-figure {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  margin: 0;
}

.tl-figure--agent img {
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: 50% 25%;
}

/* A whisper of the page's own ground, laid over the frame. */
.tl-figure::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--ground);
  opacity: var(--img-veil);
  pointer-events: none;
}

/* Two frames a generation apart: the same subject at both ends of the horizon
   a permanent policy is funded across. */
.tl-generations {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gutter);
  margin: 0;
}

.tl-generations figure {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin: 0;
}

.tl-generations figcaption {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-top: 12px;
  border-top: 1px solid var(--rule);
}

.tl-figcaption-lead {
  font-family: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-stretch: 100%;
  font-size: 1.0625rem;
  line-height: 1.3;
  letter-spacing: -0.005em;
  color: var(--ink);
}

.tl-figcaption-note {
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--ink-2);
}

@media (max-width: 767px) {
  .tl-generations {
    grid-template-columns: minmax(0, 1fr);
    gap: 32px;
  }
}

/* --------------------------------------------------------------- film -- */
/*
 * One ambient clip, muted, no audio track at all. It sits in the second half of
 * the generations diptych and does the same job the photograph does on the
 * left — it is not a hero, not a background, and never covers text.
 *
 * Three rules it has to obey:
 *   1. It never auto-starts under prefers-reduced-motion.
 *   2. It carries a real pause control, because auto-starting motion lasting
 *      more than five seconds needs one (WCAG 2.2.2).
 *   3. It costs nothing until it is scrolled to: preload="none", and playback
 *      starts and stops with an IntersectionObserver so it is not decoding
 *      frames off-screen.
 */

.tl-video {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  background: var(--ground-deep);
}

.tl-video video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: var(--img-filter);
}

/* The control sits over the frame, so it gets a solid chip of the page's own
   lifted plane rather than relying on whatever pixel is behind it. */
.tl-video-toggle {
  position: absolute;
  right: 12px;
  bottom: 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  background: var(--plane);
  border: 1px solid var(--rule-control);
  border-radius: 0;
  cursor: pointer;
  transition: border-color 90ms linear;
}

.tl-video-toggle:hover {
  border-color: var(--ink);
}

.tl-video-glyph {
  display: block;
  width: 12px;
  height: 14px;
}

/* Playing -> offer pause. Paused -> offer play. */
.tl-video-toggle[data-playing='true'] .tl-video-glyph {
  background: linear-gradient(
    to right,
    var(--ink) 0 35%,
    transparent 35% 65%,
    var(--ink) 65% 100%
  );
}

.tl-video-toggle[data-playing='false'] .tl-video-glyph {
  background: var(--ink);
  clip-path: polygon(0 0, 100% 50%, 0 100%);
}

/* With no scripting the <video> and the fallback <img> both render, stacked
   inside a box sized for one — and the UA hands the visitor native controls
   that would start exactly the download preload="none" exists to prevent. The
   poster is the whole story, so the element that would fetch the clip goes. */
html:not(.tl-js) .tl-video video {
  display: none;
}

/* With no scripting the clip never loads; the poster is the whole story. */
.tl-video-fallback {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: var(--img-filter);
}

.tl-js .tl-video-fallback {
  display: none;
}
