@charset "UTF-8";
/*! Netlogic Computer Consulting - page content components. Requires netlogic-global.css. */

/* ==========================================================================
   1. Section scaffolding and typography
   ========================================================================== */

.nl-main { display:block; }

.nl-section { padding-block:var(--nl-band); }

/* Where two sections share a ground there is no edge for a full band to
   separate, so halve it and draw the boundary instead. CSS has no "same class as
   my previous sibling" selector, so the pairs are enumerated. blue+blue and
   dark+dark do not occur today; they are here so the rule keeps holding. */
.nl-section--tint  + .nl-section--tint,
.nl-section--blue  + .nl-section--blue,
.nl-section--dark  + .nl-section--dark,
.nl-section--tint  + .nl-section--blue,
.nl-section--blue  + .nl-section--tint,
.nl-section:not(.nl-section--tint):not(.nl-section--blue):not(.nl-section--dark)
  + .nl-section:not(.nl-section--tint):not(.nl-section--blue):not(.nl-section--dark) {
  padding-top:var(--nl-seam);
  border-top:1px solid color-mix(in oklab, var(--nl-blue-900) 12%, transparent);
}
.nl-section--tint:has(+ .nl-section--tint),
.nl-section--blue:has(+ .nl-section--blue),
.nl-section--dark:has(+ .nl-section--dark),
.nl-section--tint:has(+ .nl-section--blue),
.nl-section--blue:has(+ .nl-section--tint),
.nl-section:not(.nl-section--tint):not(.nl-section--blue):not(.nl-section--dark):has(
  + .nl-section:not(.nl-section--tint):not(.nl-section--blue):not(.nl-section--dark)) {
  padding-bottom:var(--nl-seam);
}
.nl-section--dark + .nl-section--dark {
  border-top-color:color-mix(in oklab, #fff 18%, transparent);
}

/* The navy-to-white edge at a hero, and at the closing CTA, already does all the
   separating a reader needs. Paying a full band on top of it charges twice. */
.nl-hero + .nl-section,
.nl-pagehero + .nl-section { padding-top:var(--nl-seam-edge); }
.nl-section:has(+ .nl-cta)  { padding-bottom:var(--nl-seam-edge); }

/* Last-line orphans: 10 of 44 multi-line paragraphs on the home page ended with
   a final line under 28 percent of the measure, one at 12 percent. Enumerated
   rather than a blanket p rule, because pretty costs extra layout passes. */
.nl-section__lead, .nl-hero__lead, .nl-pagehero__lead,
.nl-answer p, .nl-faq__a p, .nl-acc__a p, .nl-acc__lead,
.nl-card p, .nl-svc__body, .nl-checklist span, .nl-included span,
.nl-credential__body p, .nl-proof p, .nl-cta p { text-wrap:pretty; }
.nl-section--tint { background:var(--nl-ground); }
.nl-section--blue { background:var(--nl-blue-50); }
.nl-section--dark { background:var(--nl-navy-800); color:#fff; }
.nl-section--dark .nl-section__lead { color:var(--nl-blue-300); }

.nl-section__head { max-width:56rem; margin-bottom:var(--nl-band-head); }
.nl-section__head--center { margin-inline:auto; text-align:center; }

.nl-eyebrow {
  display:inline-block; margin:0 0 14px;
  font-family:var(--nl-font-display); font-size:.76rem; font-weight:800;
  /* blue-700, not blue-500. At 12.2px this is small text and needs 4.5:1;
     blue-500 gives 3.54:1 on white and 3.28:1 on the tint, so every eyebrow on
     a light section was below AA. blue-700 is 6.53:1 and 6.05:1. The dark
     sections override to green below and are unaffected. */
  letter-spacing:.14em; text-transform:uppercase; color:var(--nl-blue-700);
}
.nl-section--dark .nl-eyebrow { color:var(--nl-green); }

.nl-h1, .nl-h2, .nl-h3 {
  font-family:var(--nl-font-display);
  text-wrap:balance; margin:0; color:inherit;
}
.nl-h1 { font-size:clamp(2.3rem, 5.2vw, 3.85rem); font-weight:800; line-height:1.05; letter-spacing:-.025em; }
.nl-h2 { font-size:clamp(1.85rem, 3.3vw, 2.7rem); font-weight:800; line-height:1.12; letter-spacing:-.02em; }
.nl-h3 { font-size:1.18rem; font-weight:700; line-height:1.3; letter-spacing:-.008em; }

.nl-section__lead {
  margin:16px 0 0;
  font-size:1.14rem; line-height:1.65; color:var(--nl-ink-2);
  /* Lato's "0" is 1.32x its average character, so ch over-delivers by a
     third. 48ch here reads as the 63-character measure it actually is. */
  max-width:48ch;
}
.nl-section__head--center .nl-section__lead { margin-inline:auto; }

/* ==========================================================================
   2. Hero
   ========================================================================== */

.nl-hero {
  position:relative; overflow:hidden;
  background:
    radial-gradient(1100px 520px at 82% -10%, rgba(50,142,210,.42), transparent 62%),
    linear-gradient(155deg, var(--nl-navy-900) 0%, var(--nl-blue-900) 58%, #0B5EA6 100%);
  color:#fff;
  padding-block:clamp(64px, 8vw, 116px) clamp(56px, 6vw, 88px);
}
/* Faint circuit-trace motif, drawn in CSS so it costs no request */
.nl-hero::after {
  content:""; position:absolute; inset:0; pointer-events:none;
  background-image:
    linear-gradient(rgba(255,255,255,.055) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.055) 1px, transparent 1px);
  background-size:64px 64px;
  mask-image:radial-gradient(900px 460px at 78% 8%, #000 0%, transparent 72%);
  -webkit-mask-image:radial-gradient(900px 460px at 78% 8%, #000 0%, transparent 72%);
}
.nl-hero__inner { position:relative; z-index:1; display:grid; grid-template-columns:1.15fr .85fr; gap:56px; align-items:center; }
.nl-hero .nl-eyebrow { color:var(--nl-green); }
.nl-hero__lead { margin:20px 0 0; font-size:1.22rem; line-height:1.6; color:#D7E7F6; max-width:44ch; }
.nl-hero__actions { display:flex; flex-wrap:wrap; gap:14px; margin-top:32px; }

.nl-hero__proof {
  display:flex; flex-wrap:wrap; gap:0 30px;
  margin:38px 0 0; padding:22px 0 0; list-style:none;
  border-top:1px solid rgba(255,255,255,.2);
}
.nl-hero__proof li { display:flex; flex-direction:column; gap:2px; padding-block:6px; }
.nl-hero__proof b {
  font-family:var(--nl-font-display); font-size:1.6rem; font-weight:800;
  line-height:1.1; color:#fff;
}
.nl-hero__proof span { font-size:.85rem; color:var(--nl-blue-300); }
.nl-hero__proof .nl-stars { font-size:1rem; letter-spacing:1px; }

/* Hero side panel: the assessment offer */
.nl-offer {
  background:rgba(255,255,255,.07);
  border:1px solid rgba(255,255,255,.22);
  border-radius:var(--nl-radius-lg);
  padding:30px 28px;
  backdrop-filter:blur(3px);
}
.nl-offer__h { margin:0 0 10px; font-family:var(--nl-font-display); font-size:1.3rem; font-weight:800; }
.nl-offer p { margin:0 0 18px; color:#D7E7F6; font-size:.98rem; }
.nl-offer__list { margin:0 0 24px; padding:0; list-style:none; display:flex; flex-direction:column; gap:11px; font-size:.96rem; }
.nl-offer__list li { display:flex; gap:11px; align-items:flex-start; }
.nl-offer__list li::before {
  content:""; flex:0 0 auto; width:18px; height:18px; margin-top:4px;
  border-radius:50%; background:var(--nl-green);
  -webkit-mask:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 6L9 17l-5-5' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/14px no-repeat, linear-gradient(#000,#000);
  -webkit-mask-composite:xor; mask-composite:exclude;
  mask:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 6L9 17l-5-5' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/14px no-repeat;
}
.nl-offer .nl-btn { width:100%; }
.nl-offer__fine { margin:14px 0 0 !important; font-size:.84rem !important; color:var(--nl-blue-300) !important; text-align:center; }

@media (max-width:980px) {
  .nl-hero__inner { grid-template-columns:1fr; gap:40px; }
}

/* ==========================================================================
   3. Answer capsule - the block search engines and assistants quote
   ========================================================================== */

.nl-answer {
  background:var(--nl-surface);
  border:1px solid var(--nl-line);
  border-left:6px solid var(--nl-green);
  border-radius:var(--nl-radius);
  box-shadow:var(--nl-shadow);
  padding:30px 34px;
  max-width:58ch;
}
.nl-answer h2 { margin:0 0 12px; font-family:var(--nl-font-display); font-size:1.32rem; font-weight:800; letter-spacing:-.01em; }
.nl-answer p { margin:0; font-size:1.08rem; line-height:1.66; color:var(--nl-ink-2); }
.nl-answer p + p { margin-top:14px; }
.nl-answer strong { color:var(--nl-ink); }

/* ==========================================================================
   4. Card grids
   ========================================================================== */

.nl-grid { display:grid; gap:22px; }
.nl-grid--2 { grid-template-columns:repeat(2, 1fr); }
.nl-grid--3 { grid-template-columns:repeat(3, 1fr); }
.nl-grid--4 { grid-template-columns:repeat(4, 1fr); }

.nl-card {
  display:flex; flex-direction:column; gap:10px;
  background:var(--nl-surface);
  border:1px solid var(--nl-line);
  border-radius:var(--nl-radius);
  padding:26px 24px;
  text-decoration:none; color:inherit;
  transition:border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
a.nl-card:hover {
  border-color:var(--nl-blue-500);
  box-shadow:var(--nl-shadow);
  transform:translateY(-3px);
}
.nl-card__icon {
  width:44px; height:44px; margin-bottom:6px;
  display:grid; place-items:center;
  border-radius:11px; background:var(--nl-blue-50); color:var(--nl-blue-900);
}
.nl-card__icon svg { width:23px; height:23px; }
.nl-card h3 { margin:0; font-family:var(--nl-font-display); font-size:1.06rem; font-weight:700; line-height:1.32; }
.nl-card p { margin:0; font-size:.96rem; color:var(--nl-ink-2); line-height:1.6; }
.nl-card__more {
  margin-top:auto; padding-top:12px;
  font-family:var(--nl-font-display); font-weight:700; font-size:.9rem; color:var(--nl-blue-700);
}
a.nl-card:hover .nl-card__more { text-decoration:underline; }

@media (prefers-reduced-motion: reduce) {
  .nl-card, a.nl-card:hover { transition:none; transform:none; }
}

@media (max-width:980px) {
  .nl-grid--3, .nl-grid--4 { grid-template-columns:repeat(2, 1fr); }
}
@media (max-width:600px) {
  .nl-grid--2, .nl-grid--3, .nl-grid--4 { grid-template-columns:1fr; }
}

/* ==========================================================================
   5. Split section with checklist
   ========================================================================== */

.nl-split { display:grid; grid-template-columns:1fr 1fr; gap:clamp(34px, 5vw, 72px); align-items:start; }

.nl-checklist { margin:0; padding:0; list-style:none; display:flex; flex-direction:column; gap:16px; }
.nl-checklist li { display:flex; gap:14px; align-items:flex-start; }
.nl-checklist li::before {
  content:""; flex:0 0 auto; width:26px; height:26px; margin-top:2px;
  border-radius:8px; background:var(--nl-green);
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 6L9 17l-5-5' fill='none' stroke='%23173D06' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-size:16px; background-position:center; background-repeat:no-repeat;
}
.nl-checklist strong { display:block; font-family:var(--nl-font-display); font-size:1.02rem; color:var(--nl-ink); line-height:1.32; margin-bottom:3px; }
.nl-checklist span { color:var(--nl-ink-2); font-size:.97rem; }

@media (max-width:900px) { .nl-split { grid-template-columns:1fr; } }

/* ==========================================================================
   6. Process
   ========================================================================== */

/* Track count follows the number of steps, so a 4-step process does not leave
   an empty fifth column. */
.nl-steps { display:grid; grid-template-columns:repeat(auto-fit, minmax(178px, 1fr)); gap:0; counter-reset:nlstep; }
.nl-step { position:relative; padding:0 20px 0 0; }
.nl-step::before {
  counter-increment:nlstep; content:counter(nlstep);
  display:grid; place-items:center;
  width:46px; height:46px; margin-bottom:18px;
  border-radius:50%; background:var(--nl-green); color:var(--nl-green-ink);
  font-family:var(--nl-font-display); font-weight:800; font-size:1.12rem;
  font-variant-numeric:tabular-nums;
}
/* connector line between steps */
.nl-step::after {
  content:""; position:absolute; top:22px; left:56px; right:0; height:2px;
  background:rgba(126,196,84,.32);
}
.nl-step:last-child::after { display:none; }
.nl-step h3 { margin:0 0 8px; font-family:var(--nl-font-display); font-size:1.04rem; font-weight:700; }
.nl-step p { margin:0; font-size:.94rem; line-height:1.6; color:var(--nl-blue-300); }

@media (max-width:1000px) {
  .nl-steps { grid-template-columns:repeat(2, 1fr); gap:34px 24px; }
  .nl-step::after { display:none; }
}
@media (max-width:560px) { .nl-steps { grid-template-columns:1fr; } }

/* ==========================================================================
   7. Values
   ========================================================================== */

.nl-values { display:grid; grid-template-columns:repeat(5, 1fr); gap:18px; margin:0; padding:0; list-style:none; }
.nl-value {
  background:var(--nl-surface); border:1px solid var(--nl-line);
  border-top:4px solid var(--nl-blue-500);
  border-radius:var(--nl-radius); padding:24px 20px;
}
.nl-value h3 { margin:0 0 7px; font-family:var(--nl-font-display); font-size:1.04rem; font-weight:800; color:var(--nl-blue-900); }
.nl-value p { margin:0; font-size:.94rem; color:var(--nl-ink-2); line-height:1.58; }

@media (max-width:1000px) { .nl-values { grid-template-columns:repeat(2, 1fr); } }
@media (max-width:560px) { .nl-values { grid-template-columns:1fr; } }

/* ==========================================================================
   8. Testimonials
   ========================================================================== */

.nl-quotes { display:grid; grid-template-columns:repeat(3, 1fr); gap:22px; }
.nl-quote {
  display:flex; flex-direction:column; gap:16px;
  background:var(--nl-surface); border:1px solid var(--nl-line);
  border-radius:var(--nl-radius); padding:28px 26px;
}
/* green-text, not green: the stars carry the rating visually, so they are
   content rather than decoration. Brand green is 2.12:1 on white. */
.nl-quote__stars { color:var(--nl-green-text); letter-spacing:3px; font-size:1.05rem; }
.nl-quote blockquote { margin:0; font-size:1rem; line-height:1.66; color:var(--nl-ink-2); }
.nl-quote figcaption { margin-top:auto; padding-top:8px; border-top:1px solid var(--nl-line-soft); font-size:.9rem; }
.nl-quote figcaption strong { display:block; font-family:var(--nl-font-display); color:var(--nl-ink); font-size:.98rem; }
.nl-quote figcaption span { color:var(--nl-ink-3); }

@media (max-width:980px) { .nl-quotes { grid-template-columns:1fr; } }

/* /reviews/ prints all 34 written reviews at once and they run from 6
   characters to 1,439. In the grid above, every card in a row stretches to the
   tallest card in that row, so one long review leaves two near-empty boxes
   beside it -- on this page, a screenful of them. CSS columns let each card
   take only the height it needs and pack the short ones together.

   `columns` on the container rather than a grid because there is no masonry in
   stable CSS yet. The tradeoff is that reading order runs down column 1 before
   column 2, which is fine here: these are independent quotes in no meaningful
   sequence, not a list anyone reads end to end.

   break-inside:avoid keeps a card from being split across two columns.
   .nl-quote is a flex column, whose `margin-top:auto` on the figcaption is a
   no-op once the height is content-driven, so the caption sits directly under
   the quote as intended. */
.nl-quotes--flow { display:block; columns:3; column-gap:22px; }
.nl-quotes--flow .nl-quote {
  break-inside:avoid; -webkit-column-break-inside:avoid;
  margin:0 0 22px;
}
@media (max-width:1180px) { .nl-quotes--flow { columns:2; } }
@media (max-width:760px)  { .nl-quotes--flow { columns:1; } }

/* ==========================================================================
   9. FAQ - answer-engine formatting
   ========================================================================== */

.nl-faq { max-width:72ch; margin-inline:auto; display:flex; flex-direction:column; gap:12px; }
.nl-faq__item {
  background:var(--nl-surface); border:1px solid var(--nl-line);
  border-radius:var(--nl-radius); overflow:hidden;
}
.nl-faq__item[open] { border-color:var(--nl-blue-500); box-shadow:var(--nl-shadow); }
.nl-faq__q {
  display:flex; align-items:flex-start; justify-content:space-between; gap:18px;
  padding:20px 24px; cursor:pointer; list-style:none;
  font-family:var(--nl-font-display); font-size:1.06rem; font-weight:700; line-height:1.4;
}
.nl-faq__q::-webkit-details-marker { display:none; }
/* The question is a real heading so it appears in the document outline.
   HTML allows one heading element as a summary's content. */
.nl-faq__q > h3 { margin:0; font:inherit; color:inherit; letter-spacing:inherit; }
.nl-faq__q::after {
  content:""; flex:0 0 auto; width:13px; height:13px; margin-top:7px;
  border-right:2.5px solid var(--nl-blue-700); border-bottom:2.5px solid var(--nl-blue-700);
  transform:rotate(45deg); transition:transform .2s ease;
}
.nl-faq__item[open] .nl-faq__q::after { transform:rotate(-135deg); margin-top:11px; }
.nl-faq__a { padding:0 24px 22px; }
.nl-faq__a p { margin:0; color:var(--nl-ink-2); line-height:1.68; }
.nl-faq__a p + p { margin-top:12px; }

@media (prefers-reduced-motion: reduce) { .nl-faq__q::after { transition:none; } }

/* ==========================================================================
   10. Closing call to action
   ========================================================================== */

.nl-cta {
  background:
    radial-gradient(760px 340px at 12% 0%, rgba(126,196,84,.24), transparent 66%),
    linear-gradient(120deg, var(--nl-blue-900) 0%, var(--nl-navy-900) 100%);
  color:#fff;
}
.nl-cta__inner {
  display:grid; grid-template-columns:1.35fr .65fr; gap:44px; align-items:center;
  padding-block:clamp(52px, 6vw, 84px);
}
.nl-cta p { margin:14px 0 0; font-size:1.1rem; color:#D7E7F6; max-width:44ch; }
.nl-cta__actions { display:flex; flex-direction:column; gap:14px; }
.nl-cta__actions .nl-btn { width:100%; }
.nl-cta__phone {
  margin:0; text-align:center; font-size:.95rem; color:var(--nl-blue-300);
}
.nl-cta__phone a { color:#fff; font-weight:700; text-decoration:none; }
.nl-cta__phone a:hover { color:var(--nl-green); }

@media (max-width:900px) { .nl-cta__inner { grid-template-columns:1fr; gap:28px; } }

/* ==========================================================================
   11. Local coverage strip
   ========================================================================== */

.nl-coverage {
  display:flex; flex-wrap:wrap; gap:10px;
  margin:26px 0 0; padding:0; list-style:none;
}
.nl-coverage li {
  font-family:var(--nl-font-display); font-size:.88rem; font-weight:700;
  color:var(--nl-blue-900); background:var(--nl-blue-100);
  padding:7px 15px; border-radius:999px;
}

/* ==========================================================================
   12. Service pages
   ========================================================================== */

.nl-breadcrumb {
  padding-block:14px;
  border-bottom:1px solid rgba(255,255,255,.16);
  font-size:.86rem;
}
.nl-breadcrumb ol { display:flex; flex-wrap:wrap; gap:8px; margin:0; padding:0; list-style:none; }
.nl-breadcrumb li { display:flex; align-items:center; gap:8px; color:var(--nl-blue-300); }
.nl-breadcrumb li + li::before { content:"/"; opacity:.5; }
.nl-breadcrumb a { color:var(--nl-blue-300); text-decoration:none; }
.nl-breadcrumb a:hover { color:#fff; text-decoration:underline; }
.nl-breadcrumb [aria-current] { color:#fff; }

.nl-pagehero {
  position:relative; overflow:hidden;
  background:
    radial-gradient(880px 420px at 88% -20%, rgba(50,142,210,.4), transparent 62%),
    linear-gradient(150deg, var(--nl-navy-900) 0%, var(--nl-blue-900) 100%);
  color:#fff;
}
.nl-pagehero__inner { padding-block:clamp(46px, 6vw, 78px); max-width:60rem; }
.nl-pagehero .nl-eyebrow { color:var(--nl-green); }
.nl-pagehero__lead { margin:18px 0 0; font-size:1.16rem; line-height:1.6; color:#D7E7F6; max-width:46ch; }
.nl-pagehero__actions { display:flex; flex-wrap:wrap; gap:13px; margin-top:28px; }
/* The same button row under a .nl-section__head--center. Left-aligned buttons
   read as a mistake beneath a centered heading, and centering is the only
   difference, so this is a modifier rather than a second component. */
.nl-pagehero__actions--center { justify-content:center; }

/* Included list: term plus explanation */
.nl-included { margin:0; padding:0; list-style:none; display:grid; grid-template-columns:1fr 1fr; gap:18px 34px; }
.nl-included li { display:flex; gap:13px; align-items:flex-start; }
.nl-included li::before {
  content:""; flex:0 0 auto; width:24px; height:24px; margin-top:3px; border-radius:7px;
  background:var(--nl-green);
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 6L9 17l-5-5' fill='none' stroke='%23173D06' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-size:15px; background-position:center; background-repeat:no-repeat;
}
.nl-included b { display:block; font-family:var(--nl-font-display); font-size:1rem; font-weight:700; color:var(--nl-ink); line-height:1.32; margin-bottom:3px; }
.nl-included span { color:var(--nl-ink-2); font-size:.95rem; }

@media (max-width:820px) { .nl-included { grid-template-columns:1fr; } }

/* Light variant of the numbered process */
.nl-steps--light .nl-step p { color:var(--nl-ink-2); }
.nl-steps--light .nl-step::after { background:rgba(10,95,168,.2); }

/* Proof callout - a named, verifiable claim */
.nl-proof {
  display:grid; grid-template-columns:auto 1fr; gap:26px; align-items:center;
  background:var(--nl-navy-800); color:#fff;
  border-radius:var(--nl-radius-lg); padding:34px 38px;
}
.nl-proof__stat {
  font-family:var(--nl-font-display); font-size:clamp(2.4rem,5vw,3.4rem); font-weight:800;
  line-height:1; color:var(--nl-green); white-space:nowrap;
}
/* Word labels wrap; numeric stats stay on one line. */
.nl-proof__stat--wrap { white-space:normal; font-size:clamp(1.7rem,3vw,2.3rem); line-height:1.04; max-width:5ch; }
.nl-proof h2 { margin:0 0 10px; font-family:var(--nl-font-display); font-size:1.3rem; font-weight:800; }
.nl-proof p { margin:0; color:#D7E7F6; max-width:48ch; }
.nl-proof p + p { margin-top:10px; }

@media (max-width:760px) { .nl-proof { grid-template-columns:1fr; gap:14px; padding:28px 24px; } }

/* Compact related-service links. Track count follows the number of cards, so a
   four-card set does not leave one orphaned on a second row. */
.nl-related { display:grid; grid-template-columns:repeat(auto-fit, minmax(248px, 1fr)); gap:18px; }
.nl-related a {
  display:flex; flex-direction:column; gap:6px;
  padding:20px 22px; text-decoration:none; color:inherit;
  background:var(--nl-surface); border:1px solid var(--nl-line); border-radius:var(--nl-radius);
}
.nl-related a:hover { border-color:var(--nl-blue-500); box-shadow:var(--nl-shadow); }
.nl-related strong { font-family:var(--nl-font-display); font-size:1.02rem; }
.nl-related span { font-size:.92rem; color:var(--nl-ink-2); }

@media (max-width:820px) { .nl-related { grid-template-columns:1fr; } }

/* Industry chips */
.nl-industry-links { display:flex; flex-wrap:wrap; gap:10px; margin:22px 0 0; padding:0; list-style:none; }
.nl-industry-links a {
  display:inline-block; padding:8px 17px; border-radius:999px;
  background:var(--nl-blue-100); color:var(--nl-blue-900);
  font-family:var(--nl-font-display); font-weight:700; font-size:.9rem; text-decoration:none;
}
.nl-industry-links a:hover { background:var(--nl-blue-500); color:#fff; }

/* ==========================================================================
   13. About and Contact
   ========================================================================== */

/* Credential groups - the E-E-A-T payload on the About page */
.nl-creds { display:grid; grid-template-columns:repeat(3,1fr); gap:22px; }
.nl-cred {
  background:var(--nl-surface); border:1px solid var(--nl-line);
  border-top:4px solid var(--nl-green); border-radius:var(--nl-radius); padding:24px 22px;
}

/* Each group is a <details open>. Open is set in the markup, so with neither CSS
   nor JS the full list shows, exactly as a plain grid would. Below 600px the
   grid drops to one column and the 20 items become a long stack, so netlogic.js
   closes them at that width only. Nothing is ever hidden unless the script ran
   AND the viewport is small, and a tap reopens it. */
.nl-cred__h { list-style:none; display:flex; align-items:center; gap:10px; cursor:default; }
.nl-cred__h::-webkit-details-marker { display:none; }
.nl-cred h3 { margin:0 0 14px; font-family:var(--nl-font-display); font-size:1.02rem; font-weight:800; color:var(--nl-blue-900); }
.nl-cred__h h3 { margin:0; }
.nl-cred__count {
  margin-left:auto; font-family:var(--nl-font-display); font-size:.75rem; font-weight:800;
  color:var(--nl-ink-3); font-variant-numeric:tabular-nums;
}
.nl-cred > ul { margin-top:14px; }
.nl-cred ul { margin:0; padding:0; list-style:none; display:flex; flex-direction:column; gap:9px; }
.nl-cred li { display:flex; gap:10px; align-items:flex-start; font-size:.94rem; color:var(--nl-ink-2); }
.nl-cred li::before {
  content:""; flex:0 0 auto; width:7px; height:7px; margin-top:9px;
  border-radius:50%; background:var(--nl-blue-500);
}
@media (max-width:900px) { .nl-creds { grid-template-columns:1fr 1fr; } }
@media (max-width:600px) {
  .nl-creds { grid-template-columns:1fr; gap:12px; }
  .nl-cred { padding:4px 18px 6px; }
  .nl-cred__h { cursor:pointer; padding:16px 0; position:relative; padding-right:26px; }
  .nl-cred__h:focus-visible { outline:2px solid var(--nl-blue-500); outline-offset:2px; }
  .nl-cred__count { margin-left:0; }
  .nl-cred__h::after {
    content:""; position:absolute; right:4px; top:calc(50% - 5px);
    width:8px; height:8px;
    border-right:2px solid var(--nl-blue-500); border-bottom:2px solid var(--nl-blue-500);
    transform:rotate(45deg); transition:transform .2s ease;
  }
  .nl-cred[open] .nl-cred__h::after { transform:rotate(-135deg); }
  .nl-cred > ul { margin:0 0 16px; }
}
@media (max-width:600px) and (prefers-reduced-motion: reduce) {
  .nl-cred__h::after { transition:none; }
}

/* Milestone figures */
.nl-figures { display:flex; flex-wrap:wrap; gap:14px 44px; margin:30px 0 0; padding:0; list-style:none; }
.nl-figures li { display:flex; flex-direction:column; gap:3px; }
.nl-figures b {
  font-family:var(--nl-font-display); font-size:2.1rem; font-weight:800; line-height:1;
  color:var(--nl-blue-900); font-variant-numeric:tabular-nums;
}
.nl-figures span { font-size:.9rem; color:var(--nl-ink-2); }
.nl-section--dark .nl-figures b { color:#fff; }
.nl-section--dark .nl-figures span { color:var(--nl-blue-300); }

/* Contact: the two routes in, kept apart on purpose */
/* min-width:0 because a grid item defaults to min-width:auto, which refuses to
   shrink below its content's min-content width. The longest unbreakable token
   here is support@netlogiccomputer.com, about 296px at this weight and size, so
   on a 320px screen the card stayed 354px wide and pushed the whole page into a
   horizontal scroll. Pairs with the overflow-wrap below: min-width alone lets
   the box shrink, and the address then spills out of it instead. */
.nl-paths { display:grid; grid-template-columns:1fr 1fr; gap:22px; }
.nl-paths > * { min-width:0; }
.nl-path {
  display:flex; flex-direction:column; gap:12px;
  border-radius:var(--nl-radius); padding:30px 28px;
  border:1px solid var(--nl-line); background:var(--nl-surface);
}
.nl-path--client { background:var(--nl-navy-800); border-color:var(--nl-navy-800); color:#fff; }
.nl-path h2 { margin:0; font-family:var(--nl-font-display); font-size:1.24rem; font-weight:800; }
.nl-path p { margin:0; font-size:.98rem; color:var(--nl-ink-2); }
.nl-path--client p { color:#D7E7F6; }
.nl-path__lines { margin:6px 0 0; padding:0; list-style:none; display:flex; flex-direction:column; gap:9px; }
.nl-path__lines a {
  font-family:var(--nl-font-display); font-weight:700; font-size:1.08rem;
  color:var(--nl-blue-700); text-decoration:none;
  /* anywhere, not break-word: only "anywhere" is taken into account when the
     browser computes min-content width, which is the measurement that was
     forcing the card wider than the screen. */
  overflow-wrap:anywhere;
}
.nl-path--client .nl-path__lines a { color:#fff; }
.nl-path--client .nl-path__lines a:hover { color:var(--nl-green); }
.nl-path .nl-btn { align-self:flex-start; margin-top:6px; }
@media (max-width:820px) { .nl-paths { grid-template-columns:1fr; } }

/* Contact layout: form beside the details */
.nl-contact { display:grid; grid-template-columns:1.25fr .75fr; gap:44px; align-items:start; }
.nl-formwrap {
  background:var(--nl-surface); border:1px solid var(--nl-line);
  border-radius:var(--nl-radius); box-shadow:var(--nl-shadow); padding:30px 28px;
}
.nl-formwrap h2 { margin:0 0 8px; font-family:var(--nl-font-display); font-size:1.4rem; font-weight:800; }
.nl-formwrap > p { margin:0 0 22px; color:var(--nl-ink-2); }
.nl-formnote { margin:18px 0 0 !important; font-size:.88rem; color:var(--nl-ink-3) !important; }

.nl-details { display:flex; flex-direction:column; gap:24px; }
.nl-detail h3 {
  margin:0 0 8px; font-family:var(--nl-font-display); font-size:.78rem; font-weight:800;
  letter-spacing:.12em; text-transform:uppercase; color:var(--nl-ink-3);
}
.nl-detail p, .nl-detail address { margin:0; font-style:normal; line-height:1.6; }
.nl-detail a { color:var(--nl-blue-700); font-weight:700; text-decoration:none; }
.nl-detail a:hover { text-decoration:underline; }

.nl-map { border:1px solid var(--nl-line); border-radius:var(--nl-radius); overflow:hidden; line-height:0; }
.nl-map iframe { display:block; width:100%; height:280px; border:0; }

@media (max-width:900px) { .nl-contact { grid-template-columns:1fr; gap:32px; } }

/* ==========================================================================
   14. Hub pages (Services and Industries indexes)
   ========================================================================== */

.nl-group + .nl-group { margin-top:clamp(38px, 4.5vw, 58px); }
/* Title and count share the first row; the note sits on its own row beneath,
   flush to the same left edge as the title.

   It used to be a single flex row of title, note, count. Because the note took
   the leftover space, its left edge landed wherever the title happened to end,
   so it started at a different x on every group and the column read as ragged.
   Putting it on its own row makes the whole stack share one left edge. */
.nl-group__head {
  display:grid;
  grid-template-columns:1fr auto;
  align-items:baseline;
  column-gap:20px; row-gap:8px;
  margin-bottom:20px; padding-bottom:12px;
  border-bottom:2px solid var(--nl-line);
}
.nl-group__h {
  grid-column:1; grid-row:1;
  margin:0; font-family:var(--nl-font-display); font-size:1.34rem; font-weight:800;
  letter-spacing:-.012em; color:var(--nl-blue-900);
}
.nl-group__note {
  grid-column:1 / -1; grid-row:2;
  margin:0; font-size:.95rem; color:var(--nl-ink-2); max-width:74ch;
}
.nl-group__count {
  grid-column:2; grid-row:1; justify-self:end;
  font-family:var(--nl-font-mono, var(--nl-font-display)); font-size:.75rem; font-weight:700;
  letter-spacing:.1em; text-transform:uppercase; color:var(--nl-ink-3);
  font-variant-numeric:tabular-nums; white-space:nowrap;
}

/* Narrow screens: a long group title plus the count on one row squeezes the
   title into a two- or three-word column. Stack them instead. */
@media (max-width:560px) {
  .nl-group__head { grid-template-columns:1fr; row-gap:6px; }
  .nl-group__count { grid-column:1; grid-row:2; justify-self:start; }
  .nl-group__note { grid-row:3; }
}

/* Industry hub card: leads with the regulation that defines the sector */
.nl-sector { position:relative; }
.nl-sector__tag {
  display:inline-block; margin-bottom:2px;
  font-family:var(--nl-font-display); font-size:.75rem; font-weight:800;
  letter-spacing:.1em; text-transform:uppercase; color:var(--nl-green-text);
}

/* ==========================================================================
   15. Case studies
   ========================================================================== */

/* At-a-glance strip under the hero */
.nl-glance {
  display:grid; grid-template-columns:repeat(auto-fit, minmax(190px, 1fr));
  gap:1px; margin:0; padding:0;
  background:var(--nl-line); border:1px solid var(--nl-line);
  border-radius:var(--nl-radius); overflow:hidden;
}
.nl-glance > div { background:var(--nl-surface); padding:18px 20px; display:flex; flex-direction:column; gap:5px; }
.nl-glance dt {
  font-family:var(--nl-font-display); font-size:.75rem; font-weight:800;
  letter-spacing:.12em; text-transform:uppercase; color:var(--nl-ink-3);
}
.nl-glance dd { margin:0; font-size:.98rem; font-weight:700; letter-spacing:-.005em; }

/* Numbered workstreams */
.nl-work { counter-reset:nlwork; display:flex; flex-direction:column; gap:30px; }
.nl-workitem { display:grid; grid-template-columns:auto 1fr; gap:20px; align-items:start; }
.nl-workitem::before {
  counter-increment:nlwork; content:counter(nlwork,decimal-leading-zero);
  font-family:var(--nl-font-display); font-size:1.5rem; font-weight:800;
  color:var(--nl-blue-500); font-variant-numeric:tabular-nums; line-height:1.15;
  padding-top:2px;
}
.nl-workitem h3 { margin:0 0 12px; font-family:var(--nl-font-display); font-size:1.14rem; font-weight:700; }
.nl-workitem ul { margin:0; padding:0; list-style:none; display:flex; flex-direction:column; gap:10px; }
.nl-workitem li { display:flex; gap:12px; align-items:flex-start; color:var(--nl-ink-2); font-size:.97rem; }
.nl-workitem li::before {
  content:""; flex:0 0 auto; width:6px; height:6px; margin-top:9px;
  border-radius:50%; background:var(--nl-green);
}
@media (max-width:600px) {
  .nl-workitem { grid-template-columns:1fr; gap:8px; }
}

/* Results */
.nl-results { display:grid; grid-template-columns:repeat(auto-fit, minmax(250px, 1fr)); gap:20px; margin:0; padding:0; list-style:none; }
.nl-result {
  background:var(--nl-surface); border:1px solid var(--nl-line);
  border-left:5px solid var(--nl-green); border-radius:var(--nl-radius);
  padding:22px 22px;
}
.nl-result h3 { margin:0 0 7px; font-family:var(--nl-font-display); font-size:1.02rem; font-weight:800; color:var(--nl-blue-900); }
.nl-result p { margin:0; font-size:.95rem; color:var(--nl-ink-2); line-height:1.58; }

/* Pull quotes from the engagement */
.nl-pullquotes { display:grid; grid-template-columns:repeat(auto-fit, minmax(280px, 1fr)); gap:20px; }
.nl-pullquote {
  margin:0; padding:26px 28px;
  background:var(--nl-navy-800); color:#fff; border-radius:var(--nl-radius-lg);
  font-family:var(--nl-font-display); font-size:1.12rem; font-weight:600; line-height:1.45;
}
.nl-pullquote::before { content:"\201C"; display:block; font-size:2.6rem; line-height:.6; color:var(--nl-green); margin-bottom:10px; }
.nl-pullquote figcaption { margin-top:14px; font-family:var(--nl-font-body); font-size:.85rem; font-weight:400; color:var(--nl-blue-300); }

/* ==========================================================================
   16. Consulting page: service detail blocks
   ========================================================================== */

/* Compact variant of the answer capsule, for answer-first blocks that sit
   directly beneath a heading rather than opening a section. */
.nl-answer--tight {
  padding:20px 24px; max-width:58ch;
  box-shadow:none; background:var(--nl-blue-50);
}
.nl-answer--tight p { font-size:1.02rem; }

.nl-label {
  margin:26px 0 12px; font-family:var(--nl-font-display);
  font-size:.75rem; font-weight:800; letter-spacing:.13em;
  text-transform:uppercase; color:var(--nl-ink-3);
}

/* A service on the consulting page: heading, answer-first line, context, list. */
.nl-svc { padding-block:clamp(30px, 3.4vw, 46px); border-top:1px solid var(--nl-line); }
.nl-svc:first-of-type { border-top:0; padding-top:0; }
.nl-svc > h3 {
  margin:0 0 16px; font-family:var(--nl-font-display);
  font-size:clamp(1.28rem, 2.1vw, 1.6rem); font-weight:800;
  letter-spacing:-.012em; line-height:1.22; color:var(--nl-blue-900);
}
.nl-svc__body { margin:18px 0 0; color:var(--nl-ink-2); max-width:56ch; line-height:1.68; }

.nl-cols2 {
  margin:0; padding:0; list-style:none;
  display:grid; grid-template-columns:1fr 1fr; gap:11px 34px;
}
.nl-cols2 li { display:flex; gap:11px; align-items:flex-start; color:var(--nl-ink-2); font-size:.97rem; }
.nl-cols2 li::before {
  content:""; flex:0 0 auto; width:19px; height:19px; margin-top:3px; border-radius:6px;
  background:var(--nl-green);
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 6L9 17l-5-5' fill='none' stroke='%23173D06' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-size:13px; background-position:center; background-repeat:no-repeat;
}
.nl-section--dark .nl-cols2 li { color:#D7E7F6; }
@media (max-width:760px) { .nl-cols2 { grid-template-columns:1fr; } }

/* State and audience pills */
.nl-pills { display:flex; flex-wrap:wrap; gap:10px; margin:24px 0 0; padding:0; list-style:none; }
.nl-pills li {
  font-family:var(--nl-font-display); font-size:.92rem; font-weight:700;
  padding:9px 18px; border-radius:999px;
  background:rgba(255,255,255,.12); color:#fff; border:1px solid rgba(255,255,255,.28);
}

/* ==========================================================================
   17. 404 page
   ========================================================================== */

.nl-404search { display:flex; gap:12px; flex-wrap:wrap; max-width:34rem; }
.nl-404search input[type="search"] {
  flex:1 1 260px; min-width:0;
  font-family:var(--nl-font-body); font-size:1rem;
  padding:14px 18px; border-radius:999px;
  border:1px solid var(--nl-line-strong, var(--nl-border-strong, #B7C7D8));
  background:var(--nl-surface); color:var(--nl-ink);
}
.nl-404search input[type="search"]:focus-visible {
  outline:3px solid var(--nl-blue-900); outline-offset:2px;
  box-shadow:0 0 0 6px rgba(255,255,255,.95); border-color:var(--nl-blue-500);
}
.nl-404search input[type="search"]::placeholder { color:var(--nl-ink-3); }

/* Chips can contain links. The pill styling lives on the li, so a bare anchor
   inside would render as default-blue underlined text. */
.nl-coverage a { color:inherit; text-decoration:none; }
.nl-coverage li:has(> a):hover { background:var(--nl-blue-500); }

/* The pill's padding sat on the <li> while the link inside stayed inline, so
   the pill measured 32px but the actual tap target was the text box inside it,
   18px tall. On a phone that is a link you have to aim at. Where there is an
   anchor, the padding moves onto it so the whole pill is the target. */
.nl-coverage li:has(> a) { padding:0; }
.nl-coverage li > a { display:block; padding:7px 15px; }

/* Footer link lists are 18px tall with a 9px gap. Fine for a mouse, tight for
   a thumb, so give them real vertical padding on small screens only. */
@media (max-width:560px) {
  .nl-footer__col ul { gap:2px; }
  .nl-footer__col ul a,
  .nl-social a { display:inline-block; padding:7px 0; }

  /* The contents list on the legal pages is a navigation list of 14 to 19
     standalone links, not prose, so the inline-link exemption does not cover
     it. Same treatment. */
  .nl-doc__toc ol { gap:2px; }
  .nl-doc__toc ol a { display:inline-block; padding:6px 0; }

  /* Phone and email. On a phone these are the two links most likely to be
     tapped in earnest, and they were the smallest targets on the page. */
  .nl-address a,
  .nl-footer__rating a { display:inline-block; padding:6px 0; }
}
.nl-coverage li:has(> a):hover a { color:#fff; }
.nl-coverage a:focus-visible { outline-offset:4px; }


/* ==========================================================================
   15. Source citation under a proof callout
   ==========================================================================
   .nl-proof sits on --nl-navy-800, so every color here is chosen against a
   dark ground. Measured in-browser against #062F5C: body 10.61:1, link 6.32:1,
   meta 7.75:1 - all clear of the 4.5:1 AA floor for normal text. The link is
   underlined because color alone is not a sufficient affordance at this size. */

.nl-proof__cite {
  margin-top:18px; padding-top:14px;
  border-top:1px solid rgba(255,255,255,.18);
  font-size:.86rem; line-height:1.55; color:#D7E7F6;
}
.nl-proof__cite a {
  font-weight:700; color:var(--nl-green);
  text-decoration:underline; text-underline-offset:2px;
  text-decoration-color:rgba(126,196,84,.55);
}
.nl-proof__cite a:hover,
.nl-proof__cite a:focus-visible { color:#fff; text-decoration-color:#fff; }
.nl-proof__cite-meta {
  display:block; margin-top:3px;
  font-size:.8rem; font-style:italic; color:#AEC8E2;
}

/* Coverage list carrying full "<service> in <City>, ST" anchors, which are much
   longer than the bare town names .nl-coverage was sized for. */
.nl-coverage--wide { grid-template-columns:1fr; gap:2px; }
.nl-coverage--wide li { width:100%; }
.nl-coverage--wide a {
  display:block; padding:9px 14px; border-radius:8px;
  color:var(--nl-blue-900); text-decoration:none; font-weight:600; font-size:.95rem;
  transition:background-color .15s ease, transform .15s ease;
}
.nl-coverage--wide a:hover { background:var(--nl-blue-050); transform:translateX(2px); }
.nl-coverage--wide a:focus-visible { outline:2px solid var(--nl-blue-500); outline-offset:2px; }
@media (min-width:720px) { .nl-coverage--wide { grid-template-columns:1fr 1fr; } }

/* ==========================================================================
   15. Accordions (the /it-consulting/ service blocks)
   ========================================================================== */

.nl-acc { display:grid; gap:12px; }

.nl-acc__item {
  background:var(--nl-white, #fff);
  border:1px solid var(--nl-line);
  border-radius:10px;
  overflow:hidden;
}
.nl-acc__item[open] { border-color:var(--nl-blue-500); }

.nl-acc__q {
  cursor:pointer; list-style:none; display:block;
  padding:18px 56px 18px 22px; position:relative;
}
.nl-acc__q::-webkit-details-marker { display:none; }
.nl-acc__q:hover { background:var(--nl-blue-050); }
.nl-acc__q:focus-visible { outline:2px solid var(--nl-blue-500); outline-offset:-2px; }

.nl-acc__q h3 {
  margin:0 0 4px; font-family:var(--nl-font-display);
  font-size:1.08rem; font-weight:800; letter-spacing:-.01em;
  color:var(--nl-blue-900);
}
.nl-acc__lead { margin:0; font-size:.95rem; color:var(--nl-ink-2); line-height:1.55;  max-width:54ch; }

/* Chevron. Rotates to point up when the item is open. */
.nl-acc__q::after {
  content:""; position:absolute; right:24px; top:26px;
  width:9px; height:9px; border-right:2px solid var(--nl-blue-500);
  border-bottom:2px solid var(--nl-blue-500);
  transform:rotate(45deg); transition:transform .2s ease;
}
.nl-acc__item[open] .nl-acc__q::after { transform:rotate(-135deg); }

.nl-acc__a { padding:2px 22px 22px; border-top:1px solid var(--nl-line); }
.nl-acc__a > :first-child { margin-top:18px; }

@media (max-width:640px) {
  .nl-acc__q { padding:16px 46px 16px 16px; }
  .nl-acc__q::after { right:18px; }
  .nl-acc__a { padding:2px 16px 18px; }
}

/* ==========================================================================
   16. Motion
   --------------------------------------------------------------------------
   All of this is progressive enhancement, and deliberately so.

   The single rule: NOTHING is ever hidden unless the browser has already
   proved it can reveal it again. Every hidden start state lives inside
   @supports for the exact feature that animates it back to visible. A browser
   without scroll-driven animations gets the finished page with no animation at
   all, which is the correct fallback for a site whose whole purpose is being
   read by people and crawlers.

   That also rules out the usual IntersectionObserver pattern: it parks content
   at opacity:0 and depends on JavaScript to bring it back. If the script fails,
   the page is blank. None of this needs JavaScript.
   ========================================================================== */

@keyframes nl-rise    { from { opacity:0; transform:translateY(28px); } to { opacity:1; transform:none; } }
@keyframes nl-fade    { from { opacity:0; }                            to { opacity:1; } }
@keyframes nl-vt-out  { to   { opacity:0; } }
@keyframes nl-vt-in   { from { opacity:0; } }
@keyframes nl-vt-lift { from { transform:translateY(9px); } }
@keyframes nl-acc-in  { from { opacity:0; transform:translateY(-6px); } to { opacity:1; transform:none; } }
@keyframes nl-hdr     { to   { box-shadow:0 2px 16px rgba(8,74,140,.15); } }

/* --- Navigating between pages ------------------------------------------
   Cross-document view transitions. Chrome and Edge honour this today, Safari
   is adding it, Firefox ignores it and simply navigates as before. There is no
   JavaScript and no single-page-app machinery: ordinary links, ordinary page
   loads, with the browser cross-fading between them. */
@view-transition { navigation: auto; }

/* Hold the chrome still while the content changes underneath it. Without these
   the header would cross-fade with itself on every navigation, which reads as a
   flicker rather than as motion. */
.nl-topbar { view-transition-name: nl-topbar; }
.nl-header { view-transition-name: nl-header; }

/* Equal duration and linear easing make old and new opacity sum to exactly 1
   every frame, which is the condition plus-lighter needs. The previous 170ms
   and 280ms curves composited source-over, bottoming out near 0.876 combined
   alpha at the midpoint, which washed the navy hero toward white and left both
   pages' text legible at once about 9px apart. */
::view-transition-old(root) {
  animation:nl-vt-out 160ms linear both;
  mix-blend-mode:plus-lighter;
}
::view-transition-new(root) {
  animation:nl-vt-in   160ms linear both,
            nl-vt-lift 260ms cubic-bezier(.16,.84,.30,1) both;
  mix-blend-mode:plus-lighter;
}

/* Naming an element does not hold it still. It pulls the element out of the root
   snapshot and gives the browser a group to animate between old and new
   geometry, so .nl-topbar (position:static) was thrown down from wherever the
   previous page had been scrolled to. Cancelling the group animation is what
   actually pins the chrome. */
::view-transition-group(nl-topbar),
::view-transition-group(nl-header) { animation:none; }
::view-transition-old(nl-topbar),
::view-transition-old(nl-header)   { animation:none; opacity:0; }
::view-transition-new(nl-topbar),
::view-transition-new(nl-header)   { animation:none; opacity:1; mix-blend-mode:normal; }

/* --- Motion within a page ----------------------------------------------
   Scroll-driven: each element has its own view() timeline, so they arrive as
   they enter the viewport and stagger naturally by position. No observers, no
   nth-child delays, and nothing runs off a timer. */
@media (prefers-reduced-motion: no-preference) {
  /* Opening a disclosure grows it, which lengthens its own view() range and
     lowers its progress, so the row faded out as it expanded. Once open, it is
     being read: settle it. */
  .nl-acc__item[open],
  .nl-faq__item[open],
  .nl-cred[open] { animation:none; opacity:1; transform:none; }

  @supports (animation-timeline: view()) {
    .nl-section .nl-grid > *,
    .nl-section .nl-related > *,
    .nl-section .nl-included > li,
    .nl-section .nl-checklist > li,
    .nl-section .nl-figures > li,
    .nl-acc__item,
    .nl-faq__item {
      animation: nl-rise linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 30%;
    }

    .nl-section__head,
    .nl-section .nl-answer {
      animation: nl-fade linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 30%;
    }
  }

  /* Header gains a shadow as the page moves under it. */
  @supports (animation-timeline: scroll()) {
    .nl-header {
      animation: nl-hdr linear both;
      animation-timeline: scroll(root);
      animation-range: 0 90px;
    }
  }

  .nl-acc__item[open] .nl-acc__a { animation: nl-acc-in 240ms ease both; }
}

/* Anyone who has asked their system for less motion gets none of it, including
   the page transitions, which are otherwise outside the reach of the media
   query above. */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
}

/* ==========================================================================
   17. Motion, part two: variety and orientation
   --------------------------------------------------------------------------
   Everything in section 16 rose upward by the same 14px, which starts to read
   as a single mechanical effect applied to a page rather than as design. These
   add direction and weight that match what each element IS: list items that
   read left to right enter from the left, pills scale up in place, figures
   settle rather than slide.

   Same rule as before, without exception: every hidden or displaced start state
   sits inside @supports for the feature that animates it back. Nothing here is
   load-triggered, so nothing is mid-animation in the first painted frame, and
   the hero is deliberately untouched because it IS that frame.
   ========================================================================== */

@keyframes nl-slide-in  { from { opacity:0; transform:translateX(-30px); } to { opacity:1; transform:none; } }
@keyframes nl-pop       { from { opacity:0; transform:scale(.88); }       to { opacity:1; transform:none; } }
@keyframes nl-settle    { from { opacity:0; transform:translateY(22px) scale(.96); } to { opacity:1; transform:none; } }
@keyframes nl-progress  { from { transform:scaleX(0); }                   to { transform:scaleX(1); } }
@keyframes nl-drift     { to   { transform:translateY(-38px); } }

/* Anchor links land below the sticky header instead of underneath it. */
html { scroll-padding-top:96px; }

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior:smooth; }

  /* Reading progress. A 3px rule at the very top, driven by document scroll.
     No script, no element in the markup, nothing to maintain. */
  @supports (animation-timeline: scroll()) {
    .nl-site::before {
      content:""; position:fixed; inset:0 0 auto 0; z-index:60;
      height:3px; transform-origin:0 50%; transform:scaleX(0);
      background:linear-gradient(90deg, var(--nl-blue-500), var(--nl-green));
      animation:nl-progress linear both;
      animation-timeline:scroll(root);
    }

    /* The hero's decorative circuit motif drifts a little as the page moves.
       Transform only, on a pseudo-element that carries no content, so there is
       nothing here that can fail to appear. */
    .nl-hero::after {
      animation:nl-drift linear both;
      animation-timeline:scroll(root);
      animation-range:0 620px;
    }
  }

  @supports (animation-timeline: view()) {
    /* Checklists and included-lists read left to right, so they arrive that way. */
    .nl-section .nl-checklist > li,
    .nl-section .nl-included > li {
      animation:nl-slide-in linear both;
      animation-timeline:view();
      animation-range:entry 0% cover 30%;
    }

    /* Coverage pills and town lists are small and many: scaling in place keeps
       them from looking like a stack of sliding bars. */
    .nl-section .nl-coverage > li {
      animation:nl-pop linear both;
      animation-timeline:view();
      animation-range:entry 0% cover 30%;
    }

    /* Figures are numbers. They settle rather than travel. */
    .nl-section .nl-figures > li {
      animation:nl-settle linear both;
      animation-timeline:view();
      animation-range:entry 0% cover 30%;
    }

    /* Closing call to action, one step slower so it reads as an arrival. */
    .nl-cta__inner > * {
      animation:nl-rise linear both;
      animation-timeline:view();
      animation-range:entry 0% cover 30%;
    }
  }
}

/* ==========================================================================
   17. Microsoft designation badge
   ========================================================================== */

/* Footer. Sits under the review rating, slightly inset so it reads as a
   credential rather than another navigation item. */
/* vertical-align:top so the two badges hang from the same line. They are
   inline-block siblings, so the default baseline alignment would offset them
   against each other the moment their heights stopped matching. */
.nl-footer__badge {
  display:inline-block; vertical-align:top; margin-top:18px; border-radius:8px;
  transition:opacity .18s ease, transform .18s ease;
}
/* margin:0 undoes `.nl-footer__brand img { margin-bottom:18px }`, which is meant
   for the footer LOGO but matches every image in the brand column, badges
   included. Two separate symptoms came from that one inherited rule:
   the Microsoft anchor measured 150x97 around a 150x79 image, so the two badges
   were different heights and the credential line below sat 18px too low; and
   inside the BBB chip, align-items:center centred the image PLUS its phantom
   bottom margin, leaving a 6px gap above the seal and 24px below it. */
.nl-footer__badge img { display:block; width:150px; height:auto; margin:0; }
.nl-footer__badge:hover { opacity:.86; transform:translateY(-1px); }
.nl-footer__badge:focus-visible { outline:2px solid var(--nl-green); outline-offset:4px; }

/* The BBB seal is supplied as transparent artwork in BBB blues, which would
   disappear into the navy footer. It sits on a white chip for the same reason
   the Microsoft badge ships with white baked in: third-party marks keep their
   own colours rather than being tinted to match the brand.

   The chip is sized to render as the SAME BOX as the Microsoft badge beside
   it: that badge is a self-contained 220x116 card (its own white fill and
   hairline border, transparent corners) displayed at 150x79, so this chip is
   pinned to 150x79 too and the seal is centred inside it. Measured, not
   eyeballed. Getting here the naive way -- padding around a 150px-wide seal --
   produced a 174x78 box, which read as the bigger, louder badge of the pair.

   There is no whitespace to trim out of the SVG: its artwork bbox is
   961.047x367.733 inside a 961.567x368.321 viewBox, i.e. tight to 0.05%. The
   seal looks heavier than the Microsoft mark because it is a dark pill that
   fills its own box edge to edge, so the fix is the chip's padding, not the
   file. box-sizing is set locally because this stylesheet does not set it
   globally, and without it the padding would push the box back over 150. */
.nl-footer__badge--chip {
  box-sizing:border-box; width:150px; height:79px; padding:15px 11px;
  background:#fff; display:inline-flex; align-items:center; justify-content:center;
  vertical-align:top;
}
.nl-footer__badge--chip img { width:100%; height:auto; }

/* Credential line, directly under the badge. The brand column reads downward as
   proof: who we are, what clients say, what Microsoft says, what the team holds.
   Sized like the rating above it so the two read as a pair. */
.nl-footer__creds { margin:14px 0 0; font-size:.92rem; }
.nl-footer__creds a { font-weight:700; }

/* On-page callout used on the Microsoft 365 and consulting pages. The badge is
   the artwork Microsoft supplies, so it keeps its own colours and sits on a
   white card rather than being tinted to match the brand. */
.nl-credential {
  display:grid; grid-template-columns:auto 1fr; gap:28px; align-items:start;
  background:var(--nl-surface); border:1px solid var(--nl-line);
  border-left:4px solid var(--nl-blue-500);
  border-radius:var(--nl-radius); padding:30px 32px;
}
.nl-credential__badge { width:200px; height:auto; flex:none; }
.nl-credential__body > :first-child { margin-top:0; }
.nl-credential__body p { margin:0 0 14px; color:var(--nl-ink-2); }
.nl-credential__body p:last-child { margin-bottom:0; }
.nl-credential__what {
  margin:18px 0 0; padding:0; list-style:none;
  display:grid; gap:10px;
}
.nl-credential__what li {
  display:grid; grid-template-columns:auto 1fr; gap:10px;
  font-size:.95rem; color:var(--nl-ink-2);
}
.nl-credential__what li::before {
  content:"\2713"; color:var(--nl-green-text); font-weight:800; line-height:1.5;
}
/* Route to the full credential list. Suppressed on that page itself. */
.nl-credential__more { margin:18px 0 0 !important; }
.nl-credential__more a {
  font-family:var(--nl-font-display); font-weight:700; font-size:.95rem;
  color:var(--nl-blue-700); text-decoration:none;
  border-bottom:2px solid transparent; transition:border-color .18s ease;
}
.nl-credential__more a::after { content:" \2192"; }
.nl-credential__more a:hover { border-bottom-color:var(--nl-blue-500); }
@media (max-width:720px) {
  .nl-credential { grid-template-columns:1fr; gap:20px; padding:24px 22px; }
  .nl-credential__badge { width:170px; }
}


/* ==========================================================================
   18. Elevation ladder and icon tiles
   ========================================================================== */

/* Resting cards lift very slightly off the ground, and the hairline softens to
   match. Thirteen cards that gain a shadow while keeping a full-strength border
   read as 2015 panels, so the two have to move together. */
.nl-card, .nl-related a, .nl-faq__item, .nl-acc__item,
.nl-value, .nl-quote, .nl-cred, .nl-result {
  box-shadow:var(--nl-elev-1);
  border-color:color-mix(in oklab, var(--nl-line) 70%, var(--nl-surface));
}
a.nl-card:hover, .nl-related a:hover,
.nl-faq__item[open], .nl-acc__item[open] { box-shadow:var(--nl-elev-2); }

/* .nl-acc__item was 10px among a site of 14px objects. */
.nl-acc__item { border-radius:var(--nl-radius); }

/* The glyph was never the problem: #084A8C on the tile is about 8:1. The TILE
   was invisible, --nl-blue-50 on white at 1.08:1, so the icon floated with no
   holder. Tint it, ring it, and thicken the stroke; the CSS stroke-width wins
   over the SVG presentation attribute, so the 13 inline icons need no edits.
   Hold at or below 15 percent: any stronger and a four-column grid starts to
   look like a control panel of buttons rather than a quiet list of services. */
.nl-card__icon {
  background:color-mix(in oklab, var(--nl-blue-500) 15%, var(--nl-surface));
  box-shadow:inset 0 0 0 1px color-mix(in oklab, var(--nl-blue-500) 26%, transparent);
  color:var(--nl-blue-900);
  transition:background-color .18s ease, box-shadow .18s ease;
}
.nl-card__icon svg { stroke-width:2; }
a.nl-card:hover .nl-card__icon {
  background:color-mix(in oklab, var(--nl-blue-500) 26%, var(--nl-surface));
}
@media (prefers-reduced-motion: reduce) { .nl-card__icon { transition:none; } }


/* Thirteen cards in four tracks left the last one alone beside three empty
   tracks, 313px of nothing, and all thirteen were geometrically identical so
   nothing led. Three double-width leads plus ten singles is 16 cells, exactly
   four full rows, and it creates the hierarchy the grid lacked. The three are
   the services the hero itself names, not an arbitrary first-child promotion. */
.nl-grid--4, .nl-grid--3 { grid-auto-flow:dense; }

@media (min-width:601px) {
  .nl-grid--4 > .nl-card--lead,
  .nl-grid--3 > .nl-card--lead { grid-column:span 2; }
  .nl-card--lead { padding:32px 30px; }
  .nl-card--lead h3 { font-size:1.3rem; }
  .nl-card--lead p  { font-size:1.02rem; max-width:46ch; }
  .nl-card--lead .nl-card__icon { width:52px; height:52px; border-radius:13px; }
  .nl-card--lead .nl-card__icon svg { width:28px; height:28px; }
}

/* ==========================================================================
   19. Photography
   ========================================================================== */

/* Aspect ratio and focal point ride on the element as custom properties, set by
   build_shared.photo(), so the box is reserved before the file arrives and the
   page never shifts. object-position keeps faces off the crop line when a wide
   photo is used in a shallow slot. */
.nl-photo { display:block; }
.nl-photo img {
  display:block; width:100%; height:100%;
  aspect-ratio:var(--nl-photo-ar, 3 / 2);
  object-fit:cover; object-position:var(--nl-photo-focal, center center);
  border-radius:var(--nl-radius);
  background:color-mix(in oklab, var(--nl-blue-900) 6%, var(--nl-surface));
}

/* Full-bleed band. Breaks the shell so the picture runs edge to edge, which is
   the one place on the site where something is allowed to be big. */
.nl-photoband { padding-block:0; }
.nl-photoband .nl-photo img {
  border-radius:0;
  aspect-ratio:auto; height:clamp(280px, 42vh, 520px);
}

/* Photo beside prose. The figure is sticky on tall screens so the picture stays
   with the text it belongs to rather than scrolling away from it. */
.nl-photosplit { display:grid; grid-template-columns:1fr 1fr; gap:clamp(30px, 4.5vw, 64px); align-items:start; }
.nl-photosplit--narrow { grid-template-columns:minmax(0, 380px) 1fr; }
.nl-photosplit .nl-photo img { box-shadow:var(--nl-elev-2); }

/* Caption. Small, quiet, and only where the picture is making a factual claim,
   such as the building sign showing the address. */
.nl-photo__cap {
  margin:12px 0 0; font-size:.86rem; color:var(--nl-ink-3); line-height:1.5;
}
.nl-section--dark .nl-photo__cap,
.nl-section--blue .nl-photo__cap { color:#A8C6E4; }

@media (max-width:820px) {
  .nl-photosplit, .nl-photosplit--narrow { grid-template-columns:1fr; }
  .nl-photosplit .nl-photo img { max-height:340px; }
}

/* ==========================================================================
   20. Wide-screen prose layout
   ========================================================================== */

/* Prose-only sections capped their text for readability but sat in a full-width
   container, so the column hugged the left and left 42 percent of the shell
   empty on the right, worse the wider the display.
 *
 * Letting the line simply run the full width is not the fix: at 989px that is
 * about 130 characters, roughly double the comfortable maximum. Instead the
 * heading moves into its own column beside the prose, which is a normal
 * editorial arrangement, uses the whole width, and leaves the measure alone.
 *
 * Applied only to shells that hold a heading and prose. Anything containing a
 * grid, list, split, accordion or photo already uses the width and is excluded,
 * which is what the long :not(:has(...)) is doing.
 *
 * Pills are deliberately not on that exclusion list. They wrap to fill whatever
 * width they are given, so a pill list sits happily in the right-hand column,
 * and leaving it out was the last place a heading kept its narrow column with
 * half the shell empty beside it.
 *
 * The exclusion list is now about whether a component NEEDS the full width,
 * not about what a section happens to contain. Lists, step sequences and pill
 * rows all reflow: .nl-cols2 is two equal tracks, .nl-steps is auto-fit from a
 * 178px minimum, .nl-coverage wraps. All three sit perfectly well in the
 * right-hand column, so a section holding one is no longer disqualified.
 *
 * That matters because the earlier, wider list produced the raggedness it was
 * meant to prevent. On the consulting page, whether a section also held a list
 * decided whether its heading sat above the prose or beside it, so the same
 * answer capsule landed at x=109 in four sections and x=562 in three and the
 * page visibly jumped left and right while scrolling. Every section on that
 * page now takes the same two-column treatment.
 *
 * What stays excluded genuinely needs the width: card grids, photo splits,
 * accordions, credential panels, quote rows and FAQ lists. */
@media (min-width: 1040px) {
  .nl-section > .nl-shell:has(> .nl-section__head + *):not(:has(
      > .nl-grid, > .nl-split, > .nl-photosplit, > .nl-related, > .nl-faq,
      > .nl-values, > .nl-quotes, > .nl-acc,
      > .nl-creds, > .nl-group, > .nl-included,
      > .nl-photo, > .nl-proof, > .nl-checklist, > .nl-credential)) {
    display:grid;
    grid-template-columns:minmax(0, 24rem) minmax(0, 1fr);
    column-gap:clamp(44px, 5vw, 84px);
    align-items:start;
  }
  .nl-section > .nl-shell:has(> .nl-section__head + *):not(:has(
      > .nl-grid, > .nl-split, > .nl-photosplit, > .nl-related, > .nl-faq,
      > .nl-values, > .nl-quotes, > .nl-acc,
      > .nl-creds, > .nl-group, > .nl-included,
      > .nl-photo, > .nl-proof, > .nl-checklist, > .nl-credential)) > .nl-section__head {
    grid-column:1; grid-row:1 / span 99; margin-bottom:0; max-width:none;
  }
  .nl-section > .nl-shell:has(> .nl-section__head + *):not(:has(
      > .nl-grid, > .nl-split, > .nl-photosplit, > .nl-related, > .nl-faq,
      > .nl-values, > .nl-quotes, > .nl-acc,
      > .nl-creds, > .nl-group, > .nl-included,
      > .nl-photo, > .nl-proof, > .nl-checklist, > .nl-credential)) > *:not(.nl-section__head) {
    grid-column:2;
  }
  /* In the narrower right-hand column the same cap leaves slack, so raise it.
     58ch in Lato reads as about 77 characters, still inside the comfortable
     range, and it fills the column rather than stopping short of it.

     The answer capsule is deliberately NOT in this list. Section 22 sizes it,
     and this selector is specific enough (0,4,0) to have silently beaten a
     plain .nl-answer rule there, which is exactly what it did on first
     attempt: the tight capsules stayed at 58ch while the page-level one
     spanned. */
  .nl-section > .nl-shell:has(> .nl-section__head) > .nl-section__lead,
  .nl-section > .nl-shell:has(> .nl-section__head) > p { max-width:58ch; }

  /* The answer capsule used to be centred here, on the reasoning that balanced
     margins read as composition while the same slack on one side reads as a
     mistake. It is now spanned instead, see section 22, so there is no slack
     left to balance. The eyebrow goes back to the left edge with it. */
}

/* ==========================================================================
   23. Body prose links
   ========================================================================== */

/* The site never set a colour for a link inside body prose. Buttons, cards,
   navigation, breadcrumbs and the footer all style their own, so the gap was
   invisible until an audit looked for it: every <a> inside a paragraph was
   falling through to the user-agent default, rgb(0, 0, 238).
 *
 * On white that is legible but obviously not ours. On the dark section of the
 * consulting page it was dark blue on navy at 1.42:1, which is close enough to
 * invisible that the link could only be found by hovering.
 *
 * Scoped to prose containers so nothing that already styles itself is touched,
 * and .nl-btn is excluded because buttons appear inside <p> for spacing.
 * Underlined on purpose: colour alone is not a sufficient affordance, and it is
 * what carries the link on dark grounds where the palette is narrower. */
.nl-main :is(p, li, dd, blockquote, .nl-section__lead, .nl-svc__body,
             .nl-group__note, .nl-doc__body, .nl-checklist span,
             .nl-included span, .nl-answer) a:not(.nl-btn):not(.nl-card):not(.nl-card__more) {
  color:var(--nl-blue-700);
  text-decoration:underline;
  text-underline-offset:2px;
  text-decoration-thickness:from-font;
}
.nl-main :is(p, li, dd, blockquote, .nl-section__lead, .nl-svc__body,
             .nl-group__note, .nl-doc__body, .nl-checklist span,
             .nl-included span, .nl-answer) a:not(.nl-btn):hover {
  color:var(--nl-blue-900);
}

/* Dark grounds. blue-100 rather than the brand green because green is 4.18:1 on
   .nl-section--blue, below AA, while blue-100 is 7.24:1 there and 10.93:1 on
   the darkest section.
 *
 * Two things this has to get right, both of which it got wrong first time.
 *
 * Specificity: the light rule above carries three :not() classes and scores
 * (0,5,1). A dark rule written as .nl-section--dark :is(...) a:not(.nl-btn)
 * scores (0,3,1) and loses, so the links stayed blue-700 on navy at 2.05:1.
 * Repeating the same :not() chain under .nl-main takes this to (0,6,1).
 *
 * Coverage: darkness is not only a section. .nl-proof, .nl-path--client and
 * .nl-pullquote are navy boxes that sit inside light sections, and they hold
 * the Microsoft citation link, the helpdesk phone number and the support
 * address. Keying off the section alone missed all of them. */
.nl-main :is(.nl-section--dark, .nl-section--blue, .nl-cta,
             .nl-proof, .nl-path--client, .nl-pullquote)
        :is(p, li, dd, blockquote, .nl-section__lead, .nl-answer,
            .nl-checklist span, .nl-proof__cite, .nl-path__lines)
        a:not(.nl-btn):not(.nl-card):not(.nl-card__more) {
  color:var(--nl-blue-100);
}
.nl-main :is(.nl-section--dark, .nl-section--blue, .nl-cta,
             .nl-proof, .nl-path--client, .nl-pullquote)
        :is(p, li, dd, blockquote, .nl-section__lead, .nl-answer,
            .nl-checklist span, .nl-proof__cite, .nl-path__lines)
        a:not(.nl-btn):not(.nl-card):not(.nl-card__more):hover {
  color:#fff;
}

/* Chips keep their own colour. A dark section is not uniformly dark: the
   coverage pills and industry chips carry a blue-100 background of their own,
   so the rule above painted blue-100 text onto a blue-100 pill and made 35
   links across 8 pages literally invisible at 1.00:1. Same specificity as that
   rule and later in the file, so it wins without another :not() escalation. */
.nl-main :is(.nl-coverage, .nl-industry-links, .nl-pills)
        :is(p, li, dd, blockquote, .nl-section__lead, .nl-answer,
            .nl-checklist span, .nl-proof__cite, .nl-path__lines)
        a:not(.nl-btn):not(.nl-card):not(.nl-card__more) {
  color:var(--nl-blue-900);
  text-decoration:none;
}

/* ==========================================================================
   22. Answer capsules on wide screens
   ========================================================================== */

/* The capsule is the answer-engine payload, and it was the narrowest thing on
   the page: a 58ch box sitting in a 1166px shell, leaving roughly half the
   section empty around it.
 *
 * The box now spans the section. The text inside does NOT: the full shell is
 * about 150 characters per line, roughly double a comfortable measure, so
 * widening the box and letting the prose follow would trade one problem for a
 * worse one. The fill comes from the panel, not from longer lines.
 *
 * The page-level capsule carries a heading, so it can do better than fill with
 * padding: the heading takes its own column and the prose sits beside it, which
 * fills the width with content. The tight variant on the consulting page is a
 * single paragraph with no heading, so it has nothing to pair with and simply
 * spans with its measure intact.
 *
 * Two breakpoints, because the two behaviours need different room. The box can
 * span as soon as the shell is wider than a comfortable measure, around 720px.
 * The heading-beside-prose split needs a 20rem column plus a 62ch column, about
 * 1040px, so it waits. Between the two the panel spans with the prose in a
 * single column. Below 720px both fall back to the base width and shrink. */
@media (min-width: 720px) {
  .nl-answer { max-width:none; }
  .nl-answer > p { max-width:62ch; }
}

@media (min-width: 1040px) {
  .nl-answer:not(.nl-answer--tight) {
    display:grid;
    grid-template-columns:minmax(0, 20rem) minmax(0, 1fr);
    column-gap:clamp(30px, 3.4vw, 56px);
    align-items:start;
  }
  .nl-answer:not(.nl-answer--tight) > h2 {
    grid-column:1; grid-row:1 / span 99; margin-bottom:0;
  }
  .nl-answer:not(.nl-answer--tight) > p { grid-column:2; max-width:62ch; }
  .nl-answer:not(.nl-answer--tight) > p + p { margin-top:14px; }

  .nl-answer--tight > p { max-width:62ch; }
}

/* ==========================================================================
   21. Long documents: privacy policy and terms
   ========================================================================== */

/* Two legal documents, 9,500 and 19,500 characters. Neither is collapsed into
   accordions: a reader should be able to scroll a legal instrument end to end
   and print it, and hiding terms behind a click invites the argument that they
   were concealed. Navigation comes from a contents list beside the prose
   instead, which also uses the width that a single measure-limited column
   leaves empty on a desktop screen. */

.nl-doc { display:block; }
.nl-doc__body > :first-child { margin-top:0; }
.nl-doc__body h2 {
  margin:clamp(30px, 3.4vw, 46px) 0 14px;
  font-family:var(--nl-font-display); font-size:clamp(1.16rem, 1.8vw, 1.4rem);
  font-weight:800; letter-spacing:-.01em; line-height:1.28; color:var(--nl-blue-900);
  /* Clears the sticky header when a contents link jumps here. */
  scroll-margin-top:calc(var(--nl-header-h) + 22px);
}
.nl-doc__body h2:first-child { margin-top:0; }
.nl-doc__body p,
.nl-doc__body li { color:var(--nl-ink-2); line-height:1.72; max-width:68ch; }
.nl-doc__body p { margin:0 0 14px; }
.nl-doc__body ul { margin:0 0 18px; padding:0; list-style:none; display:grid; gap:9px; }

/* The bullet is positioned, not laid out, because a list item here holds
   arbitrary inline content: a bold lead-in followed by a sentence, links,
   emphasis. Making the item a two-column grid works only while every item is a
   single anonymous text run. Add a <strong> and the item has three grid
   children, the sentence wraps to row two underneath the bullet, and the "auto"
   column swells to the width of the longest text while the "1fr" column
   collapses to a few characters wide. Which is exactly what shipped. */
.nl-doc__body li { position:relative; padding-left:19px; }
.nl-doc__body li::before {
  content:""; position:absolute; left:0; top:.72em;
  width:6px; height:6px; border-radius:50%;
  background:var(--nl-blue-500);
}
.nl-doc__body a { color:var(--nl-blue-700); font-weight:600; }
.nl-doc__body a:hover { text-decoration:underline; }
/* Long unbroken URLs appear inside the terms as running text. */
.nl-doc__body { overflow-wrap:anywhere; }

.nl-doc__toc { margin:0 0 clamp(30px, 3.4vw, 44px); }
.nl-doc__toch {
  margin:0 0 8px; font-family:var(--nl-font-display); font-size:.75rem;
  font-weight:800; letter-spacing:.13em; text-transform:uppercase;
  color:var(--nl-ink-3);
}
.nl-doc__note { margin:0 0 14px; font-size:.9rem; color:var(--nl-ink-3); line-height:1.5; }
.nl-doc__toc ol {
  counter-reset:nldoc; margin:0; padding:0; list-style:none;
  display:grid; gap:7px;
}
.nl-doc__toc li { counter-increment:nldoc; display:grid; grid-template-columns:1.9em 1fr; }
.nl-doc__toc li::before {
  content:counter(nldoc) ".";
  font-family:var(--nl-font-display); font-weight:700; font-size:.82rem;
  color:var(--nl-ink-3); font-variant-numeric:tabular-nums; line-height:1.5;
}
.nl-doc__toc a {
  font-size:.9rem; line-height:1.5; color:var(--nl-blue-700);
  text-decoration:none; border-bottom:1px solid transparent;
}
.nl-doc__toc a:hover { border-bottom-color:var(--nl-blue-500); }

/* Beside the prose once there is room for both, and the contents stay in view
   while the document scrolls past them. */
@media (min-width: 1000px) {
  .nl-doc {
    display:grid;
    grid-template-columns:minmax(0, 17rem) minmax(0, 1fr);
    column-gap:clamp(40px, 4.6vw, 76px);
    align-items:start;
  }
  .nl-doc__toc {
    position:sticky; top:calc(var(--nl-header-h) + 20px);
    margin:0; padding-right:8px;
    max-height:calc(100vh - var(--nl-header-h) - 48px); overflow-y:auto;
    border-right:1px solid var(--nl-line);
  }
  .nl-doc__body p,
  .nl-doc__body li { max-width:74ch; }
}

/* Printing a legal document is a real use. Drop the chrome and the contents,
   which are navigation rather than content, and let the text run. */
@media print {
  .nl-topbar, .nl-header, .nl-footer, .nl-totop, .nl-doc__toc { display:none !important; }
  .nl-doc { display:block; }
  .nl-doc__body p, .nl-doc__body li { max-width:none; color:#000; }
  .nl-pagehero { background:none !important; color:#000 !important; }
  .nl-pagehero .nl-h1, .nl-pagehero__lead, .nl-pagehero .nl-eyebrow { color:#000 !important; }
}
