/* Intelligena company site — self-hosted, no CDN, CSP-tight. */

:root {
    /* Monochromatic palette, rewritten from the warm 2026-08-20 rebrand. Backgrounds
       are white/off-white/light-gray only; every foreground colour is a muted blue,
       muted green or brown — no orange or red anywhere on the site except the logo,
       which is a designer-authored graphic with its own oxblood/navy colours baked
       into the file rather than a CSS token, so there is nothing here to keep in
       step with a palette rewrite.

       Every pair below was checked for contrast rather than picked by eye:
         --brand on --paper            5.75:1  (link text, AA at any size)
         #fff on --brand               5.75:1  (primary button label)
         --ink-soft on --paper         7.92:1
         --ink-mute on --paper-alt     5.36:1  (AA, and never used below 15px)
         --accent on --dark            6.34:1  (loop numbers, hero eyebrow)
         --brown on --paper            7.91:1  (label/eyebrow accents)
       A site that sells usability does not get to ship a 3:1 body colour. */
    --ink:        #22262b;
    --ink-soft:   #4a525c;
    --ink-mute:   #5c6570;
    --paper:      #ffffff;
    --paper-alt:  #f2f4f6;
    --line:       #e1e5e9;
    --brand:      #3f6a8c;
    --brand-dk:   #2c4d68;
    --brand-lt:   #e2ecf3;
    --accent:     #5cb98a;
    /* A muted brown, used as a foreground accent (labels, eyebrows) alongside the
       blue/green pair — the third of the three foreground hues the palette asked for. */
    --brown:      #6b4a35;
    --dark:       #23262a;
    --dark-soft:  #32363b;
    /* Muted brown-maroon, not red or orange — "no orange or red" applies here too.
       Error states stay distinguishable from --ok (green) and --brand (blue) by hue
       and are never carried by colour alone (icon/text always pairs with it). */
    --danger:     #7a4a3a;
    --danger-bg:  #f2ece7;
    --ok:         #2f6b4a;
    --ok-bg:      #e6f0ea;
    /* Rounder than the 14px this replaced. Friendliness is largely radius and
       whitespace; it is not an extra colour. */
    --radius:     20px;
    --radius-sm:  12px;
    --shadow:     0 2px 6px rgba(30,34,38,.05), 0 14px 34px rgba(30,34,38,.09);
    --wrap:       1180px;
    --font:       system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
    margin: 0;
    font-family: var(--font);
    font-size: 17px;
    line-height: 1.62;
    color: var(--ink);
    background: var(--paper);
}

img { max-width: 100%; height: auto; display: block; }

h1, h2, h3 { line-height: 1.2; margin: 0 0 .5em; letter-spacing: -.015em; }
h2 { font-size: 2rem; }
h3 { font-size: 1.2rem; }
p { margin: 0 0 1rem; }
a { color: var(--brand); }

.container { width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 0 24px; }

.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
    position: absolute; left: -9999px; top: 0; z-index: 100;
    background: var(--brand); color: #fff; padding: 12px 20px;
}
.skip-link:focus { left: 0; }

:focus-visible { outline: 3px solid var(--brand); outline-offset: 2px; }

/* --- Header ---------------------------------------------------------- */
.site-header {
    position: sticky; top: 0; z-index: 50;
    background: rgba(255,255,255,.94);
    backdrop-filter: saturate(160%) blur(8px);
    border-bottom: 1px solid var(--line);
}
.header-inner { display: flex; align-items: center; gap: 24px; min-height: 68px; }
.brand, .brand-lockup { display: flex; align-items: center; gap: 6px; text-decoration: none; color: var(--ink); }

/* The logo graphic (icon + wordmark baked into one SVG — see _brand_mark.html for the
   three colour variants). Fixed height, auto width: the file's own aspect ratio
   (~7:1) decides how wide it renders, so a taller/shorter redraw of the artwork never
   needs a second edit here. */
.brand-mark { height: 32px; width: auto; flex-shrink: 0; }
.site-nav { display: flex; gap: 18px; margin-left: auto; flex-wrap: wrap; }
.site-nav a {
    text-decoration: none; color: var(--ink-soft); font-weight: 500; font-size: .93rem;
    padding: 6px 0; border-bottom: 2px solid transparent;
}
.site-nav a:hover { color: var(--ink); }
.site-nav a.is-active { color: var(--brand); border-bottom-color: var(--brand); }

/* --- Buttons --------------------------------------------------------- */
.btn {
    display: inline-block; padding: 12px 22px; border-radius: 999px;
    font-weight: 600; font-size: .97rem; text-decoration: none; cursor: pointer;
    border: 1.5px solid transparent; transition: background .15s, color .15s, border-color .15s;
}
.btn-primary { background: var(--brand); color: #fff; }
.btn-primary:hover { background: var(--brand-dk); }
.btn-ghost { border-color: currentColor; color: inherit; background: transparent; }
.btn-ghost:hover { background: rgba(255,255,255,.12); }
.btn-sm { padding: 8px 16px; font-size: .9rem; }
.btn-lg { padding: 15px 30px; font-size: 1.03rem; }
.hero .btn-ghost { color: #fff; }

/* --- Hero (one large hero per page) ---------------------------------- */
.hero {
    background-color: var(--dark);
    background-size: cover;
    /* Wide enough that `cover` scales the image to the box's WIDTH and crops top and
       bottom, so the horizontal position is doing nothing here and centre is right. */
    background-position: center;
    color: #fff;
    border-bottom: 1px solid rgba(255,255,255,.08);
}
.hero-inner { padding: 104px 24px 96px; max-width: 860px; }
/* Every hero on this site is a photograph of people. The width is constrained on the
   CHILDREN, not on .hero-inner — that element also carries .container, whose
   `margin: 0 auto` would centre a narrowed block and push the text right, straight onto
   the faces it is meant to avoid. */
.hero-photo .hero-eyebrow,
.hero-photo .hero-title,
.hero-photo .hero-subtitle,
.hero-photo .hero-actions { max-width: 520px; }

/* A layered drop shadow used to be what held the headline off the photograph. The
   panel is that mechanism now, at every width, so the shadow is gone rather than left
   sitting under an opaque card — it was removed inside the panel rule anyway, and
   CSS nothing can ever render is worse than none.

   The eyebrow's colour is NOT part of that. Small tracked-out teal over a daylit
   window is unreadable, and it stays white on any photograph hero — the accent
   remains the accent everywhere else on the site. */
.hero-photo .hero-eyebrow { color: #fff; font-weight: 800; letter-spacing: .16em; }
.hero-eyebrow {
    text-transform: uppercase; letter-spacing: .14em; font-size: .76rem;
    font-weight: 700; color: var(--accent); margin-bottom: 18px;
}
.hero-title { font-size: clamp(2.2rem, 5vw, 3.6rem); margin-bottom: 20px; }
.hero-subtitle { font-size: clamp(1.05rem, 2vw, 1.28rem); color: rgba(255,255,255,.86); max-width: 62ch; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 32px; }

/* --- The landing hero's copy panel ------------------------------------
   The derby photograph is the one hero whose SUBJECT reaches into the headline
   column, and no amount of prompt revision moved it: six faces around a round table
   is a composition that fills the frame. Six seeds across three prompt revisions
   produced five people, five people, five people and then six with the group still
   spanning the whole width.

   So this hero does not rely on a gradient to carry its type. The copy sits on its
   own translucent panel, which makes contrast a property of the PANEL rather than of
   whatever happens to be behind it — the only way to put a headline over a picture
   of people's faces and still be able to state a contrast ratio.

   `backdrop-filter` is an enhancement on top of an already-opaque-enough background,
   never the thing doing the work: Firefox shipped it late and a user agent that
   ignores it must still get a legible headline, not a grey wash.

   The panel drops away below 900px, where the hero is narrow enough that the copy
   spans the full width anyway and a card inset inside a card reads as a mistake. */
/* `.hero-inner` is capped at 860px and also carries `.container`, whose
   `margin: 0 auto` then centres it — so a panel inside it lands in the MIDDLE of a
   1440px page rather than on the page's left gutter, over the very faces it was put
   there to avoid. The panel variant lifts the cap and lets .container's own max-width
   position it, which is what aligns it with every band below. This is the same trap
   the `.hero-photo` comment describes, one level further out. */
.hero-panel .hero-inner { max-width: var(--wrap); padding-top: 88px; padding-bottom: 84px; }
.hero-panel .hero-panel-body,
.hero-panel .hero-dots { max-width: 560px; }
/* Painted at EVERY width. It was gated to >=900px on the assumption that a narrow
   hero is narrow enough for the copy to sit on the picture with a drop shadow — and
   the phone shot settled that: white subtitle over a white tablecloth and six
   sunlit hats, held by a shadow alone and genuinely hard to read. Mobile is where
   most people meet this page, so it is the last place to make contrast conditional. */
.hero-panel .hero-panel-body {
    background: rgba(35,38,42,.72);
    backdrop-filter: saturate(140%) blur(10px);
    border: 1px solid rgba(255,255,255,.14);
    border-radius: var(--radius);
    padding: 26px 24px 24px;
}
@media (min-width: 901px) {
    .hero-panel .hero-panel-body { padding: 34px 36px 32px; }
}
/* The actions sit inside the panel, so their top margin is the gap between the
   subtitle and the button rather than a gap outside the card. */
.hero-panel .hero-actions { margin-top: 26px; }
.hero-panel .hero-subtitle { max-width: 46ch; }

/* --- The home hero's bullets ------------------------------------------
   The two remaining rotator personas' messages, folded into the single static
   hero as sub-topics rather than shown as separate rotating slides. */
.hero-bullets { list-style: none; padding: 0; margin: 18px 0 0; max-width: 46ch; }
.hero-bullets li {
    position: relative; padding-left: 22px; margin-bottom: 10px;
    font-size: .96rem; color: rgba(255,255,255,.86);
}
.hero-bullets li::before {
    content: ""; position: absolute; left: 0; top: .5em;
    width: 8px; height: 8px; border-radius: 50%; background: var(--accent);
}
.hero-bullets strong { color: #fff; }

/* --- Home hero rotator ------------------------------------------------
   Slide 0 is the SECTION's own background-image, so there are only n-1 layers and
   returning to the first slide means every layer is off. That is what makes the whole
   thing degrade: with no JavaScript the section still paints slide 0 under the first
   copy panel, and nothing here is required for that to be a correct hero. */
.hero-rotator { position: relative; overflow: hidden; }
.hero-layers { position: absolute; inset: 0; }
.hero-layer {
    position: absolute; inset: 0;
    background-size: cover; background-position: center;
    opacity: 0; transition: opacity .9s ease-in-out;
}
/* The layers must crop the SAME WAY the section does. Slide 0 is the section's own
   background and slides 1..n are these, so a narrow-width rule that moved one and not
   the other would show the first slide following the subject and every later slide
   still centred on empty backdrop — a rotator that appears to drift. No page renders
   layers today; this is here because the mechanism is deliberately kept alive
   (see test_hero_rotator) and a half-applied rule is how it would come back broken. */
@media (max-width: 1100px) {
    .hero-layer { background-position: 68% center; }
}
.hero-layer.is-active { opacity: 1; }
/* The copy has to sit above the layers, and .hero-inner is the only positioned
   ancestor it can take a stacking context from. */
.hero-rotator .hero-inner { position: relative; z-index: 1; }

/* Grid-stacked, not absolutely positioned: every panel occupies the same cell, so the
   TALLEST one sets the hero's height once. Absolute positioning would collapse the
   height to the actions block and make the page jump on every slide change. */
.hero-copies { display: grid; }
.hero-copy {
    grid-area: 1 / 1;
    opacity: 0; visibility: hidden;
    transition: opacity .55s ease-in-out, visibility 0s linear .55s;
}
.hero-copy.is-active {
    opacity: 1; visibility: visible;
    transition: opacity .55s ease-in-out, visibility 0s;
}

.hero-dots { display: flex; gap: 10px; margin-top: 34px; flex-wrap: wrap; }
.hero-dot {
    width: 34px; height: 5px; padding: 0; border: 0; border-radius: 999px;
    background: rgba(255,255,255,.55);
    cursor: pointer; transition: background .25s ease, transform .25s ease;
    /* A 5px-tall control is far under the 24px minimum target size, so the hit area is
       extended with padding the eye never sees. */
    box-sizing: content-box;
    border-top: 10px solid transparent; border-bottom: 10px solid transparent;
    background-clip: content-box;
}
.hero-dot:hover { background: rgba(255,255,255,.62); background-clip: content-box; }
/* Outside the panel and directly on the photograph, so a 5px bar at 34% alpha over
   sunlit grass is invisible. The shadow is what makes it a control you can see. */
.hero-dot { box-shadow: 0 1px 6px rgba(31,22,16,.55); }
.hero-dot.is-active { background: var(--accent); background-clip: content-box; }
.hero-dot:focus-visible {
    outline: 2px solid #fff; outline-offset: 3px;
}

/* An auto-advancing hero is precisely what this preference is about. The timer is
   stopped in hero.js as well — stripping the transition alone would still move the
   content, just abruptly. */
@media (prefers-reduced-motion: reduce) {
    .hero-layer,
    .hero-copy { transition: none; }
}

/* --- Bands ----------------------------------------------------------- */
.band { padding: 76px 0; }
.band-alt { background: var(--paper-alt); }
.band-intro { padding: 56px 0 12px; }
.band-dark { background: var(--dark); color: rgba(255,255,255,.86); }
.band-dark h2, .band-dark h3 { color: #fff; }
.lede { font-size: 1.24rem; line-height: 1.6; color: var(--ink-soft); max-width: 68ch; }
.lede-sm { font-size: 1.08rem; color: var(--ink-soft); font-weight: 500; }
/* Larger and italic, per the user's own wording — originally scoped to the company
   page only, then extended 2026-09-09 to the tech, products and ux page ledes so
   every marketing page's under-header paragraph matches. company-lede stays a
   selector on this rule (rather than being folded away) since a test pins it as
   a standalone rule with its own declarations. */
.lede-emphasis,
.company-lede { font-size: 1.5rem; font-style: italic; }
.section-title { font-size: clamp(1.7rem, 3vw, 2.3rem); }
/* A large decorative icon beside a section heading — the company page's "About",
   "How we got here", "How the company is paid", "The team" and "The company". */
.section-heading { display: flex; align-items: center; gap: 16px; }
.section-icon {
    width: 40px; height: 40px; flex-shrink: 0;
    fill: none; stroke: var(--brand); stroke-width: 1.5;
    stroke-linecap: round; stroke-linejoin: round;
}
.section-sub { color: var(--ink-mute); max-width: 62ch; margin-bottom: 36px; }
.band-dark .section-sub { color: rgba(255,255,255,.68); }
.mini-title { font-size: .82rem; text-transform: uppercase; letter-spacing: .1em; color: var(--ink-mute); margin-top: 22px; }
.footnote-inline { color: var(--ink-mute); font-size: .95rem; margin-top: 24px; max-width: 66ch; }

.ticks { list-style: none; padding: 0; margin: 14px 0 0; }
.ticks li { position: relative; padding-left: 26px; margin-bottom: 9px; font-size: .95rem; color: var(--ink-soft); }
.ticks li::before {
    content: ""; position: absolute; left: 4px; top: .55em;
    width: 9px; height: 9px; border-radius: 50%; background: var(--accent);
}
.band-dark .ticks li { color: rgba(255,255,255,.8); }

.text-link { font-weight: 600; text-decoration: none; }
.text-link:hover { text-decoration: underline; }

/* --- Landing: the fundamentals --------------------------------------- */
.fundamental-grid {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
    gap: 22px;
}
.fundamental-card {
    background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius);
    padding: 26px 28px 24px; box-shadow: var(--shadow);
    display: flex; flex-direction: column;
}
/* Decorative, monochromatic (single stroke colour, no fill) — added for visual
   interest on the tech page's layer cards. `stroke="currentColor"` is not used
   here because the card also carries near-black body text; the icon is coloured
   independently via --brand so it reads as an accent, not as text. */
.layer-icon {
    width: 30px; height: 30px; margin-bottom: 14px;
    fill: none; stroke: var(--brand); stroke-width: 1.6;
    stroke-linecap: round; stroke-linejoin: round;
}
.fundamental-card h3 { font-size: 1.12rem; margin-bottom: 10px; }
.fundamental-summary { color: var(--ink-soft); font-size: .97rem; font-style: italic; }
/* Pushed to the bottom so the "in our apps" half of every card lines up across the
   row however long the principle above it happens to be. */
.fundamental-practice {
    margin: auto 0 0; padding-top: 16px; border-top: 1px solid var(--line);
    font-size: .92rem; color: var(--ink-soft);
}
/* Same bullet idiom as .ticks (small dot marker), reused here so the "in our apps"
   list stays visually consistent with the rest of the site. */
.fundamental-list { list-style: none; padding: 0; margin: 8px 0 0; }
.fundamental-list li { position: relative; padding-left: 22px; margin-bottom: 7px; }
.fundamental-list li:last-child { margin-bottom: 0; }
.fundamental-list li::before {
    content: ""; position: absolute; left: 2px; top: .5em;
    width: 7px; height: 7px; border-radius: 50%; background: var(--brown);
}
.fundamental-tag {
    display: block; font-size: .72rem; text-transform: uppercase; letter-spacing: .12em;
    font-weight: 700; color: var(--brown); margin-bottom: 6px;
}

/* --- Landing: the experimentation loop ------------------------------- */
.loop-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 18px; }
.loop-step {
    display: grid; grid-template-columns: 68px minmax(0, 1fr); gap: 22px; align-items: start;
    background: var(--dark-soft); border: 1px solid rgba(255,255,255,.09);
    border-radius: var(--radius); padding: 24px 28px;
}
/* The card paints its own dark background, so it carries its own foreground.
   Left to inherit, an h3 here is --ink on --dark-soft the moment this component
   is used outside a .band-dark — which the tech page does. */
.loop-step h3 { font-size: 1.08rem; margin-bottom: 6px; color: #fff; }
.loop-step p { margin: 0; color: rgba(255,255,255,.78); font-size: .97rem; }
/* Muted-green chip, filling the step's 68px left column — reuses the already
   contrast-checked --ok / --ok-bg pairing (see .verify-badge), not a new colour.
   Qualified with `.loop-step` (rather than reaching for `!important`) so it
   out-specifies `.loop-step p`'s own color/font-size above — the same trap
   `.loop-step .moment-number` (below) was already written to avoid; a bare
   `.loop-number` rule here was silently overridden by that p rule, rendering as
   small pale-white digits instead of a large dark-green numeral. */
.loop-step .loop-number {
    font-size: 2.6rem; font-weight: 800; color: var(--ok); margin: 0;
    line-height: 1; font-variant-numeric: tabular-nums;
    background: var(--ok-bg); border-radius: var(--radius-sm);
    width: 68px; height: 68px;
    display: flex; align-items: center; justify-content: center;
}

/* --- Alpha badge ------------------------------------------------------ */
.badge {
    display: inline-block; border-radius: 999px; padding: 5px 14px;
    font-size: .74rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
    margin: 0 0 12px;
}
.badge-alpha { background: var(--brand-lt); color: var(--brand-dk); border: 1px solid #c7dbe8; }

/* --- Landing: product teasers ---------------------------------------- */
.teaser-grid {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
    gap: 26px;
}
/* The card IS the anchor — see home.html. Everything inside it is inline-level, so
   the block layout has to be restated here rather than inherited from <article>. */
.teaser-card {
    display: block; text-decoration: none; color: inherit;
    background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius);
    overflow: hidden; box-shadow: var(--shadow);
    transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.teaser-card:hover {
    transform: translateY(-3px); border-color: var(--brand);
    box-shadow: 0 4px 10px rgba(30,34,38,.07), 0 20px 44px rgba(30,34,38,.13);
}
/* Monochrome — grayscale plus a very slight blue tint so the thumbnails read as
   part of the muted palette rather than as a plain desaturation. The same filter
   is applied to the full-size illustrations on /products/ (.product-figure img,
   below), so the app icons read as one consistent treatment site-wide. */
.teaser-image {
    width: 100%; aspect-ratio: 4 / 3; object-fit: cover; background: var(--paper-alt);
    filter: grayscale(1) sepia(.12) hue-rotate(170deg) saturate(1.4);
}
.teaser-body { display: block; padding: 22px 26px 26px; }
.teaser-name { display: block; font-size: 1.35rem; font-weight: 700; line-height: 1.2; margin-bottom: 4px; }
.teaser-tagline { display: block; color: var(--ink-soft); }
.teaser-more { display: block; margin-top: 14px; font-weight: 600; color: var(--brand); }
.teaser-card:hover .teaser-more { text-decoration: underline; }
.band-action { margin: 38px 0 0; }

/* --- A soft band ------------------------------------------------------ */
.band-soft { background: var(--paper-alt); }

/* --- Company: about paragraph + team grid ------------------------------ */
.about-copy { font-size: 1.08rem; line-height: 1.7; color: var(--ink-soft); max-width: 74ch; }

/* Not an anchor grid like .teaser-card — nobody clicks a person, so it is a
   plain <li> list rather than a list of links. */
.team-grid {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
    gap: 30px; list-style: none; padding: 0; margin: 0;
}
.team-card { text-align: center; }
.team-photo {
    width: 132px; height: 132px; border-radius: 50%; object-fit: cover;
    background: var(--paper); border: 1px solid var(--line); box-shadow: var(--shadow);
    margin: 0 auto 14px;
}
.team-name { font-weight: 700; font-size: 1.05rem; margin: 0; }
.team-role { color: var(--ink-mute); margin: 2px 0 0; }
.team-note { color: var(--ink-soft); font-size: .92rem; margin: 8px 0 0; max-width: 24ch; margin-left: auto; margin-right: auto; }

/* --- Company: the filed facts ------------------------------------------
   A label/value pair per row, in two columns: every dt in the left column,
   every dd in the right — the classic two-column definition-list layout, which
   `max-content 1fr` gives for free from a flat dt/dd sequence with no extra
   wrapper markup needed. Previously unstyled and relying on the browser's
   default <dl> (a single stacked column, dt not bold). */
.company-facts {
    display: grid; grid-template-columns: max-content minmax(0, 1fr);
    column-gap: 28px; row-gap: 14px; align-items: baseline;
}
.company-facts dt { font-weight: 700; color: var(--ink); margin: 0; white-space: nowrap; }
.company-facts dd { margin: 0; color: var(--ink-soft); }
.company-facts address.company-address { font-style: normal; }
@media (max-width: 560px) {
    /* A "label | value" row is too tight under ~560px once labels start
       wrapping ("Address for legal notices"), so it drops to one column. */
    .company-facts { grid-template-columns: 1fr; row-gap: 4px; }
    .company-facts dt { margin-top: 10px; }
}

/* --- Launch: the product bands ---------------------------------------- */
.product-layout {
    display: grid; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
    gap: 56px; align-items: center;
}
/* Alternating rows, so the page does not read as two identical blocks. Done with
   `order` on the FIGURE, so the DOM order — name before picture — stays the reading
   order in every case; and driven by a class the TEMPLATE assigns, because
   `:nth-of-type` here counts every <section> on the page rather than the products. */
.product-band-mirrored .product-figure { order: 2; }
.product-figure img {
    width: 100%; border-radius: var(--radius); box-shadow: var(--shadow);
    background: var(--paper-alt);
    filter: grayscale(1) sepia(.12) hue-rotate(170deg) saturate(1.4);
}
/* The header is sticky at 68px, and `html { scroll-behavior: smooth }` means a jump
   to #int_lms from the landing page's teaser card parks the product's name UNDER it —
   the page moves, the thing you asked for is hidden, and it reads as a link that went
   to the wrong place. */
.product-band { scroll-margin-top: 88px; }
.product-name { font-size: clamp(1.8rem, 3.4vw, 2.5rem); margin-bottom: 6px; }
.product-tagline { font-size: 1.2rem; color: var(--ink); font-weight: 600; margin-bottom: 14px; }
.product-who { color: var(--ink-mute); font-size: .95rem; }
.product-cta { margin: 26px 0 0; }

/* --- The dotted terms list: /products/ (dark) and /tech/ (light) ------- */
/* Authored white for the alpha terms on /products/, which is a .band-dark. The tech
   page renders the same component inside .band-soft — white on --paper-alt is 1.05:1,
   so the copy was invisible and only the accent dots showed. Same shape as .ticks
   below: a light default, and the dark band overrides it. Exactly the mistake
   .loop-step's comment above already describes, pointing the other way. */
.terms-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 14px; max-width: 74ch; }
.terms-list li {
    position: relative; padding-left: 30px;
    color: var(--ink-soft); font-size: 1.02rem;
}
.band-dark .terms-list li { color: rgba(255,255,255,.82); }
.terms-list li::before {
    content: ""; position: absolute; left: 0; top: .5em;
    width: 12px; height: 12px; border-radius: 50%; background: var(--accent);
}

/* --- Contact: the aside ------------------------------------------------ */
.reason-list { list-style: none; padding: 0; margin: 0 0 10px; }
.reason-list li { padding: 16px 0; border-bottom: 1px solid var(--line); }
.reason-list li:last-child { border-bottom: 0; }
.reason-list h3 { font-size: 1rem; margin-bottom: 4px; }
.reason-list p { font-size: .93rem; color: var(--ink-soft); margin: 0; }
.confirmation-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 22px; }

/* --- CTA ------------------------------------------------------------- */
.band-cta { background: linear-gradient(120deg, var(--brand-dk) 0%, var(--brand) 62%, #6f9db8 100%); color: #fff; }
.cta-inner { display: flex; align-items: center; justify-content: space-between; gap: 30px; flex-wrap: wrap; }
.cta-inner h2 { margin-bottom: 6px; }
.cta-inner p { margin: 0; color: rgba(255,255,255,.86); }
.band-cta .btn-primary { background: #fff; color: var(--brand-dk); }
.band-cta .btn-primary:hover { background: var(--brand-lt); }

/* --- Partner form ---------------------------------------------------- */
.partner-layout { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, .85fr); gap: 60px; align-items: start; }
.form-title { font-size: 1.7rem; }
.form-intro { color: var(--ink-mute); margin-bottom: 26px; }
.partner-form .field { margin-bottom: 20px; }
.partner-form label { display: block; font-weight: 600; font-size: .93rem; margin-bottom: 7px; }
.req { color: var(--danger); margin-left: 3px; }
.partner-form input[type="text"],
.partner-form input[type="email"],
.partner-form select,
.partner-form textarea {
    width: 100%; padding: 12px 14px; font: inherit; font-size: .98rem; color: var(--ink);
    background: var(--paper); border: 1.5px solid var(--line); border-radius: var(--radius-sm);
}
.partner-form textarea { resize: vertical; min-height: 140px; }
.partner-form input:focus, .partner-form select:focus, .partner-form textarea:focus {
    border-color: var(--brand); outline: 3px solid rgba(63,106,140,.18); outline-offset: 0;
}
.field.has-error input, .field.has-error select, .field.has-error textarea { border-color: var(--danger); background: var(--danger-bg); }
.field-help { font-size: .85rem; color: var(--ink-mute); margin: 6px 0 0; }
.field-error { font-size: .88rem; color: var(--danger); font-weight: 600; margin: 7px 0 0; }
.form-error {
    background: var(--danger-bg); border: 1px solid #e3cfc4; border-left: 5px solid var(--danger);
    color: #4a2e22; border-radius: var(--radius-sm); padding: 16px 20px; margin-bottom: 26px;
}
.form-actions { margin-top: 30px; }
.form-note { font-size: .87rem; color: var(--ink-mute); margin: 12px 0 0; }
/* Honeypot. `display:none` (not off-screen positioning) so the field is out of the
   visual tree, the a11y tree AND the tab order — an off-screen input is still
   "visible" to assistive tech and to a keyboard user. Hidden inputs are still
   submitted, which is the whole point; it is never `required`, so it cannot block
   a submit. */
.hp-wrap { display: none; }

.confirmation {
    background: var(--ok-bg); border: 1px solid #b7d9c5; border-left: 5px solid var(--ok);
    border-radius: var(--radius); padding: 34px 36px;
}
.confirmation h2 { color: var(--ok); font-size: 1.5rem; }

.partner-aside { background: var(--paper-alt); border: 1px solid var(--line); border-radius: var(--radius); padding: 30px 32px; }
.aside-title { font-size: 1.12rem; margin-top: 26px; }
.aside-title:first-child { margin-top: 0; }
.engagement-list { list-style: none; padding: 0; margin: 0 0 10px; }
.engagement-list li { padding: 16px 0; border-bottom: 1px solid var(--line); }
.engagement-list li:last-child { border-bottom: 0; }
.engagement-list h3 { font-size: 1rem; margin-bottom: 2px; }
.engagement-duration { font-size: .82rem; text-transform: uppercase; letter-spacing: .08em; color: var(--brown); font-weight: 700; margin-bottom: 8px; }
.engagement-list p { font-size: .93rem; color: var(--ink-soft); margin: 0; }

/* Reach-us-directly block on /contact/ — outside <noscript> on purpose, so the
   entity, address and phone are readable even when the form itself cannot run. */
.contact-identity { font-style: normal; font-size: .93rem; line-height: 1.6; color: var(--ink-soft); margin: 14px 0 10px; }
.contact-identity strong { color: var(--ink); }
.contact-direct { list-style: none; padding: 0; margin: 0; font-size: .95rem; }
.contact-direct li { margin-bottom: 6px; }

/* --- Footer ---------------------------------------------------------- */
.site-footer { background: var(--dark); color: rgba(255,255,255,.7); padding: 56px 0 30px; margin-top: 0; }
.footer-inner { display: flex; justify-content: space-between; gap: 34px; flex-wrap: wrap; padding-bottom: 26px; border-bottom: 1px solid rgba(255,255,255,.1); }
.footer-brand p { margin: 6px 0 0; font-size: .95rem; }
.footer-nav { display: flex; flex-wrap: wrap; gap: 20px; align-items: center; }
.footer-nav a { color: rgba(255,255,255,.78); text-decoration: none; font-size: .94rem; }
.footer-nav a:hover { color: #fff; text-decoration: underline; }
.footer-legal { padding-top: 22px; }
.footer-legal p { font-size: .82rem; color: rgba(255,255,255,.5); margin: 0 0 6px; max-width: 90ch; }
/* The legal row had NO rule of its own and fell through to `a { color: var(--brand) }`
   — a link colour chosen for white paper, rendered on the near-black footer. It was
   already under 3:1 with the old blue and the warm palette only made it visible; a
   colour that is wrong on both palettes was never a palette problem. */
.footer-legal-links { display: flex; flex-wrap: wrap; gap: 18px; margin-bottom: 12px; }
.footer-legal-links a { color: rgba(255,255,255,.86); text-decoration: none; font-size: .88rem; }
.footer-legal-links a:hover { color: #fff; text-decoration: underline; }
/* The SAME defect, on the same ground, missed when the rule above was written: the
   telephone and the support address inside the shared identity block are links too,
   also had no rule of their own, and were also still inheriting the paper link colour —
   measured in the browser at 2.98:1 against a 4.5 floor. A fix aimed at the selector
   somebody was looking at rather than at every link on that background. The shared
   int_legal block ships no stylesheet of its own, so the colour must come from here. */
.site-footer .int-legal-identity a { color: rgba(255,255,255,.86); text-decoration: underline; }
.site-footer .int-legal-identity a:hover { color: #fff; }

/* The staff console, and the only link in the footer that is not part of the public
   site. Quieter than its neighbours on purpose — it is here so somebody who needs it
   can find it, not to be found by somebody who does not. Quieter, NOT unreadable:
   --ink-mute is a token for warm paper and lands at about 2:1 on this ground. */
.footer-internal { color: rgba(255,255,255,.55) !important; }
.footer-internal:hover { color: #fff !important; }

.env-badge {
    display: inline-block; background: var(--accent); color: var(--dark);
    border-radius: 6px; padding: 3px 12px; font-weight: 700; font-size: .76rem !important;
    letter-spacing: .06em;
}

/* --- The technology summary on the landing page ------------------------
   Two columns: the claim, and three things it cashes out as. The band is NOT a
   link — it holds a list, and a list inside an anchor is one tab stop that a
   screen reader announces as one run-on sentence. The button is the target. */
.band-tech { background: var(--brand-lt); }
.tech-summary {
    display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
    gap: 48px; align-items: start;
}
.section-eyebrow {
    text-transform: uppercase; letter-spacing: .14em; font-size: .76rem;
    font-weight: 700; color: var(--brand-dk); margin: 0 0 14px;
}
.tech-summary-copy p { color: var(--ink-soft); max-width: 56ch; }
/* `.band-action` centres nothing on its own but carries a 38px top margin meant for
   a full-width row under a grid. Inside a column it only needs the margin. */
.band-action-left { margin-top: 26px; }
.tech-summary-points { margin-top: 8px; }
.tech-summary-points li { font-size: 1rem; color: var(--ink); margin-bottom: 16px; }

/* --- The tech page's contrast table -----------------------------------
   A real <table>: it IS tabular — the same four questions answered two ways — and
   a row header announced before each cell is the only way it reads correctly
   without sight of the columns.

   `.table-scroll` is the wrapper, and it is not optional. A three-column table of
   prose cannot narrow past its content, so without its own scroller the PAGE BODY
   scrolls sideways on a phone and every other section goes with it. tabindex makes
   the scroller reachable by keyboard, which is the half of `overflow-x` that is
   usually forgotten — a region you can only scroll by dragging is a region a
   keyboard user cannot read the right-hand side of. */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table-scroll:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.contrast-table { width: 100%; min-width: 720px; border-collapse: collapse; text-align: left; }
.contrast-table th, .contrast-table td {
    padding: 18px 22px; vertical-align: top;
    border-bottom: 1px solid rgba(255,255,255,.12);
}
.contrast-table thead th {
    font-size: .78rem; text-transform: uppercase; letter-spacing: .12em;
    color: rgba(255,255,255,.62); font-weight: 700; padding-bottom: 10px;
}
.contrast-table tbody th {
    width: 26%; color: #fff; font-weight: 700; font-size: 1rem;
}
.contrast-table td { color: rgba(255,255,255,.7); font-size: .95rem; }
/* Our column is the one being argued for, so it is the one that reads as present
   rather than as a footnote. Weight and a left rule, never colour alone —
   "colour is never the only thing carrying a meaning" is one of the eight. */
.contrast-table .contrast-ours {
    color: #fff; border-left: 2px solid var(--accent); background: rgba(43,179,163,.07);
}
.contrast-table tbody tr:last-child th,
.contrast-table tbody tr:last-child td { border-bottom: 0; }

/* The numeral gets its OWN column — the same first grid column .loop-step
   already reserves (68px) — as a dark number in a white circle, rather than
   sharing it with the product name. `.loop-number`'s own font-size/weight are
   NOT reused here: that class is styled for bare accent-coloured type directly
   on the dark card, which is the wrong look inside a filled circle.

   Both rules are qualified with `.loop-step` (rather than reaching for
   `!important`) so they out-specify `.loop-step p`'s own margin/color/font-size,
   which would otherwise win the cascade against a bare class of equal weight. */
.loop-step .moment-number {
    width: 40px; height: 40px; margin: 0; border-radius: 50%;
    background: #fff; color: var(--ink);
    display: flex; align-items: center; justify-content: center;
    font-size: 1.15rem; font-weight: 800; font-variant-numeric: tabular-nums;
}
/* The product name moved into the content column, as a small label above the
   heading — the same role .fundamental-tag plays on the layer cards above. */
.loop-step .moment-product {
    display: block; font-size: .82rem; text-transform: uppercase;
    letter-spacing: .1em; font-weight: 700; color: var(--accent);
    margin: 0 0 6px;
}

/* "Plus many more.." — a short trailing line under the four examples. .section-sub
   has no top margin of its own (only bottom), so this adds the gap under the list. */
.moments-more { margin-top: 18px; }

/* --- Responsive ------------------------------------------------------ */
@media (max-width: 900px) {
    .partner-layout, .product-layout, .tech-summary { grid-template-columns: 1fr; gap: 32px; }
    /* Reset the alternation with the columns it exists to alternate. */
    .product-band-mirrored .product-figure { order: 0; }
    .hero-inner { padding: 72px 24px 64px; }
    .band { padding: 56px 0; }
}
/* Below ~1100px the hero is TALLER than the image's aspect, so `cover` flips: it
   scales to the box's HEIGHT and crops horizontally instead. A centred crop then
   shows the middle of the frame — and every hero on this site deliberately puts its
   subject RIGHT of centre, in the half the copy panel does not cover. So the middle
   of the frame is the one part of these photographs with nobody in it, and a phone
   was getting a sliver of empty studio wall behind the panel.

   68% rather than `right`: hard right-alignment crops INTO the subject at the frame
   edge — the group hero's rightmost person and the skydiver's parachute both lose
   their outer edge. 68% was picked by rendering 60/68/75 at 390px and comparing:
   at 60 and 75 the contact portrait is cut through the eyes and the skydiver shows
   canopy instead of a face, while the group stays legible at all three.

   Measured, not assumed: 1100px is where the hero box (656px tall) passes the 1.78:1
   of a 16:9 hero, and it is below the 1100px width at which the copy panel stops
   being a half-width column. */
@media (max-width: 1100px) {
    .hero { background-position: 68% center; }
}

@media (max-width: 680px) {
    .header-inner { flex-wrap: wrap; min-height: 0; padding-top: 12px; padding-bottom: 12px; }
    .site-nav { order: 3; width: 100%; margin-left: 0; gap: 16px; }
    .loop-step { grid-template-columns: 1fr; gap: 6px; }
    .cta-inner { flex-direction: column; align-items: flex-start; }
}
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    * { transition: none !important; }
}

/* --- Work-email verification (partner form) ---------------------------
   Rendered by the server and shown/hidden by marketing/partner-verify.js. The
   [hidden] rules are explicit because `.verify-row { display: flex }` would
   otherwise beat the attribute's own UA rule and show a row that is meant to be
   gone — the classic "hidden element still on screen" flex bug. */
.verify-block { margin-top: 10px; }
.verify-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.verify-block [hidden] { display: none !important; }

.btn-outline {
    background: transparent; color: var(--brand); border-color: var(--brand);
}
.btn-outline:hover:not(:disabled) { background: var(--brand-lt); }
.partner-form .btn:disabled { opacity: .5; cursor: not-allowed; }

.btn-link {
    background: none; border: 0; padding: 0; font: inherit; font-size: .88rem;
    color: var(--brand); text-decoration: underline; cursor: pointer;
}
.btn-link:disabled { color: var(--ink-mute); text-decoration: none; cursor: not-allowed; }

.verify-badge {
    display: inline-flex; align-items: center; gap: 6px;
    background: var(--ok-bg); color: var(--ok); border: 1px solid #b7d9c5;
    border-radius: 999px; padding: 5px 14px; font-size: .88rem; font-weight: 700;
}

.verify-code { margin-top: 12px; }
.verify-code label {
    display: block; font-weight: 600; font-size: .88rem; margin-bottom: 6px;
}
/* Narrower than a normal field: a six-character box that spans the form reads as
   somewhere to write a sentence. */
.partner-form .verify-code input[type="text"] {
    width: 9.5em; letter-spacing: .28em; font-variant-numeric: tabular-nums;
    text-align: center;
}

.verify-status { font-size: .88rem; color: var(--ink-mute); margin: 9px 0 0; }
.verify-status:empty { margin: 0; }
.verify-status-error { color: var(--danger); font-weight: 600; }

/* The widget paints its own card; this only keeps it in the form's rhythm. */
.captcha-field altcha-widget { display: block; max-width: 320px; }
