/* ==========================================================================
   NOLVIS DESIGN SYSTEM
   --------------------------------------------------------------------------
   One design system for the whole site. The corporate pages sit on NOLVIS
   Black with Electric Cyan as the accent; the structural language borrowed
   from the X1 page stays — 1px hairlines, machined 2-3px corners, numbered
   section eyebrows, tabular figures.

   Surface context is a token flip, not a second stylesheet: :root is the black
   ground and every component reads the tokens rather than naming colours. The
   light-surface tokens are kept even though nothing uses them today — they are
   the documented half of the palette (design.md 3.2) and the starting point
   for any white section.

   This is the only stylesheet the site loads, so the brand webfonts are
   declared here and every page gets them.

   Rules whose selectors no longer appear in any page were removed on
   2026-07-31; the component vocabulary they belonged to is recorded in
   design.md 6.2 and the markup is in _archive.
   ========================================================================== */

/* --- 0. Webfonts --- */
/* Avenir was the brand face and used to be self-hosted here. The font files and
   their @font-face rules were removed on 2026-09-01. "Avenir" / "Avenir Next"
   stay in --font-family-sans (section 1), so the face is used only where the
   device already has it installed; everything else falls through the stack. */

/* IBM Plex Mono carries the technical labels only (--font-label). Split by
   unicode-range so the Pi file — arrows, primes, box drawing — is fetched only
   by the pages that actually use those glyphs. */
@font-face{font-family:'IBM Plex Mono';src:url('assets/fonts/IBMPlexMono-Medium-Latin1.woff2') format('woff2');font-weight:500;font-style:normal;font-display:swap;unicode-range:U+0020-007E,U+00A0-00FF,U+0131,U+0152-0153,U+02C6,U+02DA,U+02DC,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2039-203A,U+2044,U+20AC,U+2122,U+2212,U+FB01-FB02}
@font-face{font-family:'IBM Plex Mono';src:url('assets/fonts/IBMPlexMono-Medium-Pi.woff2') format('woff2');font-weight:500;font-style:normal;font-display:swap;unicode-range:U+2032-2033,U+2190-2199,U+2212,U+221E,U+2500-259F}
@font-face{font-family:'IBM Plex Mono';src:url('assets/fonts/IBMPlexMono-SemiBold-Latin1.woff2') format('woff2');font-weight:600;font-style:normal;font-display:swap;unicode-range:U+0020-007E,U+00A0-00FF,U+0131,U+0152-0153,U+02C6,U+02DA,U+02DC,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2039-203A,U+2044,U+20AC,U+2122,U+2212,U+FB01-FB02}
@font-face{font-family:'IBM Plex Mono';src:url('assets/fonts/IBMPlexMono-SemiBold-Pi.woff2') format('woff2');font-weight:600;font-style:normal;font-display:swap;unicode-range:U+2032-2033,U+2190-2199,U+2212,U+221E,U+2500-259F}

/* --- 1. Variables & Design Tokens --- */
:root {
  /* Brand palette (design.md 3) */
  --color-black: #000000;   /* NOLVIS Black    */
  --color-white: #ffffff;   /* NOLVIS White    */
  --color-navy: #1A1A2E;    /* Deep Space Navy */

  /* Electric Cyan has two jobs, because it cannot do both. On black it is the
     accent for everything — marks, rules, links. On white it measures 1.4:1
     and is unreadable as text, so the deepened teal takes over wherever a
     light surface is in play (the X1 page; see .x1-page below). */
  --color-accent: #00E5FF;           /* marks, rules, links on dark         */
  --color-accent-hover: #00b8cc;
  --color-accent-contrast: #001318;  /* ink placed on an accent fill        */
  --color-accent-ink: var(--color-accent);  /* dark surfaces: cyan reads fine */
  --color-accent-ink-light: #0a7d8c; /* the light-surface substitute, 4.7:1  */
  --accent-glow: rgba(0, 229, 255, 0.15);

  /* Surfaces — black is the ground; every tone above it sits on the brand's
     navy axis rather than on arbitrary greys. */
  --surface: #000000;
  --surface-soft: #0A0A12;           /* navy 40% on black — bands, footer   */
  --surface-card: #12121F;           /* navy 70% on black — cards, panels   */
  --surface-dark: #1A1A2E;
  --surface-dark-2: #222239;
  --surface-dark-deep: #101020;
  --surface-light: #ffffff;          /* used by .x1-page                    */
  --surface-light-soft: #f5f6f9;

  /* Rules */
  --line: #1A1A2E;                   /* hairline on black — navy 100%       */
  --line-strong: rgba(255, 255, 255, 0.25);  /* outlined controls           */
  --line-light: #e3e5ec;             /* hairline on white — used by .x1-page */
  --line-dark: #31314e;

  /* Ink */
  --ink: #ffffff;                    /* body copy                           */
  --ink-2: rgba(255, 255, 255, 0.72);/* secondary copy                      */
  --ink-3: rgba(255, 255, 255, 0.50);/* labels, captions                    */
  --ink-4: rgba(255, 255, 255, 0.30);/* disabled, fine print                */
  --ink-on-dark: #ffffff;
  --ink-2-on-dark: rgba(255, 255, 255, 0.72);
  --ink-on-light: #0d0f16;           /* used by .x1-page                    */
  --ink-2-on-light: #43485a;

  /* Typography (design.md 4). Avenir is no longer shipped (section 0), so it
     applies only on devices that already have it. Windows now resolves to
     Calibri and macOS to Avenir Next, so rendering differs by platform.
     Japanese falls through per character to Hiragino / Yu Gothic. */
  --font-family-sans: "Avenir", "Avenir Next", "Calibri", "Hiragino Kaku Gothic Pro",
    "Hiragino Kaku Gothic ProN", "Helvetica Neue", Arial, "Yu Gothic", sans-serif;
  /* Drawing-annotation labels: captions, chips, stat labels */
  --font-label: "IBM Plex Mono", ui-monospace, "Cascadia Code", Consolas,
    "Courier New", monospace;

  /* Machined edges — square enough to read as instrumentation, not SaaS */
  --radius: 3px;
  --radius-s: 2px;

  /* Logo lockup: clear space is 1x, where x = cap height of the wordmark "N". */
  --logo-symbol-size: 32px;

  /* Layout */
  --container-max-width: 1240px;

  /* Animations */
  --transition-fast: 0.2s cubic-bezier(0.25, 0.8, 0.25, 1);
  --transition-normal: 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
  --transition-slow: 0.6s cubic-bezier(0.25, 0.8, 0.25, 1);
}

/* --- 2. CSS Resets & Base Styles --- */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  scroll-behavior: smooth;
  background-color: var(--surface);

  /* Type scale, matched to the X1 LP.

     X1 renders at zoom:.85 above 1100px, and the sizes here were ported from
     it as literal px — so without that factor the desktop view came out ~18%
     larger than the reference site. Zoom itself is not the answer (it also
     scales images and hit targets, and was dropped on purpose), so the root
     size carries it and only above the same 1100px threshold. Below that X1
     runs unzoomed, and so does this.

     Everything sized in rem rides along: type and vertical rhythm both. Layout
     that must not move is in px — nav height, logo, container width.
     Dial this one number to retune the whole desktop page. */
  font-size: 100%;
}

@media (min-width: 1100px) {

  html {
    /* 1rem = 13.6px from here up. 0.875rem is 11.9px, not 14px. */
    font-size: 85%;
  }

}

body {
  background-color: var(--surface);
  color: var(--ink);
  font-family: var(--font-family-sans);
  font-weight: 400;
  line-height: 1.62;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  /* Drives the numbered section eyebrows (see .eyebrow-label / .eyebrow) */
  counter-reset: sec;
}

/* --- 3. Core Typography --- */
h1, h2, h3, h4, h5, h6 {
  font-weight: 900;
  line-height: 1.05;
  letter-spacing: -0.025em;
  color: var(--ink);
}

/* The heading scale is X1's own, restated in rem so the root rule above scales
   it on desktop exactly as X1's zoom does. X1 declares, in px:
   h1 clamp(34,4.6vw,52) · h2 clamp(27,3.2vw,36) · h3 19 · h4-h6 inherit. */
h1 {
  font-size: clamp(2.125rem, 4.6vw, 3.25rem);
}

h2 {
  font-size: clamp(1.6875rem, 3.2vw, 2.25rem);
  line-height: 1.1;
}

h3 {
  font-size: 1.1875rem;
  line-height: 1.2;
}

h4 {
  font-size: 1.0625rem;
}

p {
  font-size: 0.97rem;
  color: var(--ink-2);
}

a {
  color: var(--color-accent-ink);
  text-decoration: none;
  transition: color var(--transition-fast);
}

a:hover {
  color: var(--ink);
}

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

/* Figures read as instrument readouts, not prose */
.spec-value {
  font-variant-numeric: tabular-nums lining-nums;
}

/* --- 3b. Dark sections ---------------------------------------------------
   Any block that opts into the navy surface flips the ink tokens for its
   subtree, so the same components work on both surfaces without a second set
   of classes. Add .on-dark to the <section>. */
.footer-component {
  background-color: var(--surface-dark-deep);
  color: var(--ink-on-dark);
  --ink: var(--ink-on-dark);
  --ink-2: var(--ink-2-on-dark);
  --ink-3: rgba(255, 255, 255, 0.55);
  --ink-4: rgba(255, 255, 255, 0.34);
  --line: var(--line-dark);
  --surface: var(--surface-dark-deep);
  --surface-soft: var(--surface-dark);
  --surface-card: var(--surface-dark-2);
  /* On dark, cyan is legible again — links stop needing the deepened teal. */
  --color-accent-ink: var(--color-accent);
}

.footer-component h1,
.footer-component h2,
.footer-component h3,
.footer-component h4 {
  color: var(--ink-on-dark);
}

/* --- 4. Client-First Structure & Layout Utilities --- */
.page-wrapper {
  position: relative;
  width: 100%;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.main-wrapper {
  flex: 1 0 auto;
  width: 100%;
}

.container-large {
  width: 100%;
  max-width: var(--container-max-width);
  margin-left: auto;
  margin-right: auto;
}

/* Fluid side margins for global layout spacing */
.padding-global {
  padding-left: clamp(20px, 5vw, 64px);
  padding-right: clamp(20px, 5vw, 64px);
}

/* Section vertical spaces */
.padding-section-large {
  padding-top: clamp(96px, 14vh, 180px);
  padding-bottom: clamp(96px, 14vh, 180px);
}

.padding-section-medium {
  padding-top: clamp(64px, 10vh, 110px);
  padding-bottom: clamp(64px, 10vh, 110px);
}

/* Margins (Margin-bottom elements to avoid margin collapse issues) */
.margin-bottom-xsmall { margin-bottom: 0.5rem; }
.margin-bottom-small  { margin-bottom: 1.5rem; }
.margin-bottom-medium { margin-bottom: 2.5rem; }
.margin-bottom-large  { margin-bottom: 3.5rem; }
.margin-top-small  { margin-top: 1.5rem; }

/* Grid systems with fluid gaps */
.grid-2-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(32px, 4.5vw, 64px);
  align-items: center;
}

.grid-3-col {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: clamp(20px, 2.5vw, 32px);
}

@media (max-width: 920px) {

  .grid-2-col { grid-template-columns: 1fr; }
  .grid-3-col { grid-template-columns: 1fr 1fr; }

}

@media (max-width: 700px) {

  .grid-3-col { grid-template-columns: 1fr; }

}

/* Flexbox layouts */
.flex-column {
  display: flex;
  flex-direction: column;
}

/* Text size & alignment utilities (Client-First) */
/* Lead paragraphs — the same clamp X1 uses for .lead, in rem. */
.text-size-large {
  font-size: clamp(1.0625rem, 1.9vw, 1.1875rem);
  line-height: 1.6;
}

.text-size-small {
  font-size: 0.875rem;
}
.text-color-muted { color: var(--ink-3); }

/* --- 5. UI Components --- */

/* Section eyebrow — a dimension annotation, not a coloured label.
   .eyebrow-label (corporate markup) and .eyebrow (X1 markup) are the same
   component and are defined once here. Adding .is-numbered prints the running
   section number, the way the X1 page numbers its sections. */
.eyebrow-label {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 0.75rem;   /* X1 sets its eyebrows at a flat 12px */
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--ink);
}

/* The trailing rule is what makes it read as an annotation */
.eyebrow-label::after {
  content: "";
  width: 34px;
  height: 1px;
  background: currentColor;
  opacity: 0.35;
}

/* The eyebrow holds a proper noun rather than a section label — the product
   name on the placeholder pages. No running number, and the name is printed
   as written: "Nolvis X1", not "NOLVIS X1". The label tracking is eased off
   with it, because 0.2em pulls a mixed-case name apart. */
.eyebrow-label.is-plain {
  text-transform: none;
  letter-spacing: 0.08em;
}

.eyebrow-label.is-plain::before {
  content: none;
}

/* Main Navigation */
.nav-component {
  position: sticky;
  top: 0;
  background-color: rgba(0, 0, 0, 0.85);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
  z-index: 1000;
  width: 100%;
}

.nav-container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 80px;
}

/* Brand lockup (design.md 2) — Horizontal variation. The header now sits on
   white, so it carries the Black-on-White artwork; the footer keeps its navy
   surface and the White-on-Black artwork. The official files are used as
   single locked images; never rearrange, recolour, rescale one part, distort,
   or add effects. Clear space is 1x on all sides, where x = the "N" cap height. */
.nav-brand {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

.brand-logo {
  /* The SVG viewBox bakes in the mandated 1x clear space, so the visible glyphs
     sit at ~73% of the box height — the rendered height is set larger than the
     24px lockup minimum (design.md 2) so the wordmark reads at the intended size. */
  height: 40px;
  width: auto;
  display: block;
}

/* Footer keeps the navy surface, so it keeps the White-on-Black lockup. */
.footer-component .brand-logo {
  height: 38px;
}

.nav-menu {
  display: flex;
  align-items: center;
  gap: 2rem;
  list-style: none;
}

/* Set as written, like the product names in the dropdown below it — a nav bar
   that shouts one row and speaks the next reads as two systems. Japanese has
   no case to transform, so the two language trees also match now. */
.nav-link {
  font-size: 0.875rem;
  font-weight: 400;
  letter-spacing: 0.05em;
  color: var(--ink-2);
  text-transform: none;
  transition: color var(--transition-fast);
}

.nav-link:hover,
.nav-link.w--current {
  color: var(--color-accent-ink);
}

/* Nav dropdown (Products submenu) */
.nav-item-has-dropdown {
  position: relative;
  display: flex;
  align-items: center;
  height: 80px;
}

.nav-dropdown {
  list-style: none;
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 200px;
  background-color: rgba(0, 0, 0, 0.95);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity var(--transition-fast), transform var(--transition-fast), visibility var(--transition-fast);
  z-index: 1001;
}

.nav-item-has-dropdown:hover .nav-dropdown,
.nav-item-has-dropdown:focus-within .nav-dropdown {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

/* The dropdown lists product names, so unlike the top-level nav it is set as
   written — "Nolvis M1", not "NOLVIS M1". */
.nav-dropdown-link {
  display: block;
  padding: 10px 14px;
  font-size: 0.813rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: none;
  color: var(--ink-2);
  border-radius: 2px;
  white-space: nowrap;
  transition: background-color var(--transition-fast), color var(--transition-fast);
}

.nav-dropdown-link:hover {
  background-color: var(--surface-soft);
  color: var(--color-accent-ink);
}

/* Mobile Nav Toggle */
.nav-toggle {
  display: none;
  background: none;
  border: none;
  color: var(--ink);
  font-size: 1.5rem;
  cursor: pointer;
}

@media (max-width: 920px) {

  .nav-menu {
    display: none; /* Collapsed by default; toggled open via .is-open (see script.js) */
  }
  .nav-menu.is-open {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 1.5rem;
    position: absolute;
    top: 80px;
    left: 0;
    right: 0;
    background-color: rgba(0, 0, 0, 0.96);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--line);
      padding: 24px clamp(20px, 5vw, 64px);
  }
  .nav-toggle {
    display: block;
  }

  /* Dropdown becomes a static, always-visible indented list when the
     mobile menu is open (hover/focus is not reliable on touch). */
  .nav-item-has-dropdown {
    height: auto;
    flex-direction: column;
    align-items: flex-start;
    width: 100%;
  }
  .nav-dropdown {
    position: static;
    opacity: 1;
    visibility: visible;
    transform: none;
    background: none;
    border: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    min-width: 0;
    padding: 12px 0 0 16px;
  }

}

/* Language switcher (EN / 日本語) — no markup uses these right now: the site is
   English-only since the /ja/ tree was retired (see _backup/README.md). Kept so
   the switcher styles itself again if the Japanese edition comes back. */
.lang-switch {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-left: 8px;
  border-left: 1px solid var(--line);
}

.lang-switch-link {
  font-size: 0.813rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--ink-3);
  transition: color var(--transition-fast);
}

.lang-switch-link:hover {
  color: var(--color-accent);
}

.lang-switch-link[aria-current="true"] {
  color: var(--ink);
}

@media (max-width: 920px) {

  .lang-switch {
    padding-left: 0;
    border-left: none;
    padding-top: 8px;
    border-top: 1px solid var(--line);
    width: 100%;
  }

}

/* Japanese pages: relax the uppercase/wide-tracking treatment that only
   suits Latin text, and use a Japanese-capable font stack. */
:lang(ja) body,
body:lang(ja) {
  font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", "Yu Gothic",
    "Meiryo", var(--font-family-sans);
}

:lang(ja) .nav-link,
:lang(ja) .nav-dropdown-link,
:lang(ja) .eyebrow-label,
:lang(ja) .footer-column-title,
:lang(ja) .button {
  text-transform: none;
}

:lang(ja) h1,
:lang(ja) h2,
:lang(ja) h3 {
  letter-spacing: 0.01em;
}

:lang(ja) p,
:lang(ja) li {
  line-height: 1.9;
}

/* Footer Section — the site's closing dark band. The token flip it shares with
   .on-dark (section 3b) is what lets the White-on-Black lockup stay correct. */
.footer-component {
  padding-top: 80px;
  padding-bottom: 40px;
}

.footer-top {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  gap: clamp(32px, 4vw, 64px);
  margin-bottom: 60px;
}

@media (max-width: 700px) {

  .footer-top {
    grid-template-columns: 1fr;
    gap: 40px;
  }

}

/* Set as written, in step with the nav and the links underneath it. The
   tracking eases off with the caps — 0.12em was spacing for uppercase. */
.footer-column-title {
  font-size: 0.875rem;
  font-weight: 700;
  text-transform: none;
  letter-spacing: 0.04em;
  color: var(--ink-on-dark);
  margin-bottom: 24px;
}

.footer-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.footer-list-link {
  font-size: 0.938rem;
  color: var(--ink-3);
  transition: color var(--transition-fast);
}

.footer-list-link:hover {
  color: var(--color-accent);
}

.footer-bottom {
  border-top: 1px solid var(--line);
  padding-top: 30px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 20px;
}

.footer-bottom-text {
  font-size: 0.813rem;
  color: var(--ink-3);
}

/* Buttons -----------------------------------------------------------------
   One button system. `.button*` is the corporate markup and `.btn*` the X1
   markup; they are the same component and are declared together so there is a
   single place to change them. The clipped top-right corner on the primary
   button is the machined edge the X1 direction is built on. */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 15px 26px;
  font-size: 0.845rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  border-radius: var(--radius-s);
  transition: background-color var(--transition-fast), border-color var(--transition-fast),
    color var(--transition-fast), transform var(--transition-fast);
  cursor: pointer;
  border: 1px solid transparent;
}

.button-primary {
  background-color: var(--color-accent);
  color: var(--color-accent-contrast);
  border-color: var(--color-accent);
  clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 0 100%);
}

.button-primary:hover {
  background-color: var(--color-accent-hover);
  border-color: var(--color-accent-hover);
  color: var(--color-accent-contrast);
  transform: translateY(-1px);
}

/* Outlined, for light surfaces */
.button-secondary {
  background-color: transparent;
  color: var(--ink);
  border-color: var(--line-strong);
}

.button-secondary:hover {
  border-color: var(--ink);
  color: var(--ink);
  transform: translateY(-1px);
}

.button-group {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

/* Cards (Product, Resource, Profile) */
.card-product {
  position: relative;
  background-color: var(--surface-card);
  border: 1px solid var(--line);
  padding: clamp(24px, 3vw, 48px);
  border-radius: var(--radius);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: 100%;
  transition: border-color var(--transition-normal), transform var(--transition-normal), box-shadow var(--transition-normal);
}

/* The whole card is clickable. Rather than wrap it in a second anchor — which
   would give every card two tab stops and nest links — the button already at
   the foot of the card stretches an invisible layer over the card. One link,
   one focus ring, and the button's own hover state now answers to the whole
   card. The usual trade-off applies: text inside the card is not selectable. */
.card-link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.card-product:hover {
  border-color: var(--color-accent-ink);
  transform: translateY(-4px);
  box-shadow: 0 10px 30px var(--accent-glow);
}

.card-image-wrap {
  width: 100%;
  aspect-ratio: 16/10;
  background-color: var(--surface-soft);
  position: relative;
  overflow: hidden;
  border-radius: 1px;
  margin-bottom: 24px;
}

.card-image-wrap img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--transition-slow);
}

.card-product:hover .card-image-wrap img {
  transform: scale(1.05);
}

/* E-E-A-T Profile Card */
.card-profile {
  background-color: var(--surface-card);
  border: 1px solid var(--line);
  border-radius: 2px;
  overflow: hidden;
  transition: border-color var(--transition-fast);
}

.card-profile:hover {
  border-color: rgba(255, 255, 255, 0.2);
}

.profile-image-wrap {
  width: 100%;
  aspect-ratio: 1/1;
  background-color: var(--surface-soft);
}

.profile-image-wrap img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.profile-content {
  padding: 24px;
}

.profile-name {
  font-size: 1.25rem;
  font-weight: 900;
  margin-bottom: 4px;
}

.profile-title {
  font-size: 0.813rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--color-accent);
  letter-spacing: 0.1em;
  margin-bottom: 16px;
}

.profile-bio {
  font-size: 0.875rem;
  color: var(--ink-2);
  margin-bottom: 16px;
}

/* Resource Card */
.card-resource {
  background-color: var(--surface-card);
  border: 1px solid var(--line);
  padding: 24px;
  display: flex;
  flex-direction: column;
  transition: border-color var(--transition-fast);
}

.card-resource:hover {
  border-color: var(--color-accent);
}

/* Cards whose article has not been written yet. The title is no longer a link,
   so the card stops lighting up under the cursor as if it were one, and the
   call to action reads as a status instead. */
.card-resource.is-pending:hover {
  border-color: var(--line);
}

.resource-status {
  color: var(--ink-3);
  font-weight: 700;
}

.resource-meta {
  display: flex;
  gap: 12px;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-accent);
  margin-bottom: 12px;
}

.resource-category {
  background: var(--accent-glow);
  padding: 2px 8px;
  border-radius: 1px;
}

.resource-title-link {
  font-size: 1.25rem;
  font-weight: 900;
  line-height: 1.2;
  color: var(--ink);
  margin-bottom: 12px;
}

/* Only a real link reacts — the same class is used on the plain titles of
   articles that are still being written. */
a.resource-title-link:hover {
  color: var(--color-accent);
}

.resource-excerpt {
  font-size: 0.875rem;
  color: var(--ink-2);
}

/* --- 6. Specific Layout Sections & Wrappers --- */

/* Hero video / visual container */
.hero-visual-wrapper {
  position: relative;
  width: 100%;
  aspect-ratio: 16/9;
  background-color: var(--surface-dark-deep);
  border: 1px solid var(--line);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* The reel fills the 16/9 wrapper. Both clips are 16/9 themselves, so cover
   crops nothing; it is there to keep the frame filled if a later clip is not.

   script.js stacks a second element in the same box and hands over between
   clips. The one waiting its turn is transparent, so the clip on screen stays
   on screen — including its last frame while the next one buffers — and the
   change reads as a dissolve rather than a blink. */
.hero-reel-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background-color: var(--surface-dark-deep);
  transition: opacity 0.3s linear;
}

.hero-reel-video.is-idle {
  opacity: 0;
}

.hero-video-play-btn {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background-color: var(--color-accent);
  color: var(--color-black);
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  font-size: 1.5rem;
  cursor: pointer;
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
  margin-bottom: 16px;
}

.hero-video-play-btn:hover {
  transform: scale(1.1);
  box-shadow: 0 0 25px var(--color-accent);
}

/* AIO Summary Box (Optimized for both AI bots and human readers) */
.aio-summary-box {
  background: linear-gradient(180deg, var(--surface-card) 0%, rgba(12, 12, 18, 0.5) 100%);
  border: 1px dashed var(--color-accent);
  padding: 32px;
  border-radius: 2px;
  position: relative;
  overflow: hidden;
}

.aio-summary-box::before {
  content: "At a Glance";
  position: absolute;
  top: 10px;
  right: 15px;
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  color: var(--color-accent);
  opacity: 0.5;
}

.aio-summary-title {
  font-size: 1.125rem;
  font-weight: 900;
  margin-bottom: 16px;
  color: var(--ink);
  display: flex;
  align-items: center;
  gap: 8px;
}

.aio-summary-title::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  background-color: var(--color-accent);
  border-radius: 50%;
}

.aio-summary-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.aio-summary-list li {
  font-size: 0.938rem;
  color: var(--ink-2);
  padding-left: 20px;
  position: relative;
}

.aio-summary-list li::before {
  content: "↳";
  position: absolute;
  left: 0;
  color: var(--color-accent);
}

/* Lead Contact Form */
.contact-form {
  background-color: var(--surface-card);
  border: 1px solid var(--line);
  padding: clamp(24px, 4vw, 48px);
  border-radius: 2px;
}

.form-group {
  margin-bottom: 24px;
}

.form-label {
  font-size: 0.813rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--ink);
  margin-bottom: 10px;
  display: block;
}

.form-input {
  width: 100%;
  background-color: var(--surface-card);
  border: 1px solid var(--line);
  padding: 14px 20px;
  color: var(--ink);
  font-family: var(--font-family-sans);
  font-size: 0.938rem;
  border-radius: 2px;
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.form-input:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 12px var(--accent-glow);
}

textarea.form-input {
  resize: vertical;
  min-height: 150px;
}

/* Hubspot/Integration placeholder indicators */
.form-footer-note {
  font-size: 0.75rem;
  color: var(--ink-3);
  line-height: 1.4;
  margin-top: 16px;
}

/* Tech Grid Pattern overlay for sections */
.grid-overlay {
  position: relative;
}

.grid-overlay::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: 
    linear-gradient(rgba(0, 229, 255, 0.03) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 229, 255, 0.03) 1px, transparent 1px);
  background-size: 60px 60px;
  z-index: 0;
  pointer-events: none;
}

.z-1 {
  position: relative;
  z-index: 1;
}

.subnav-link {
  display: block;
  padding: 4px 0;
  border-bottom: 2px solid transparent;
  font-size: 0.8125rem;
  font-weight: 400;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--ink-2);
  transition: color var(--transition-fast), border-color var(--transition-fast);
}

.subnav-link:hover {
  color: var(--ink);
}

.subnav-link.is-active {
  color: var(--color-accent-ink);
  border-bottom-color: var(--color-accent-ink);
}

.kit-shot .card-image-wrap {
  aspect-ratio: 4/3;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.kit-card {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px;
  text-align: center;
  background-color: var(--surface-card);
  cursor: pointer;
  transition: border-color var(--transition-fast);
  font: inherit;
  color: inherit;
}

.kit-card:hover {
  border-color: var(--color-accent-ink);
}

.kit-card.is-selected {
  border-color: var(--color-accent-ink);
  box-shadow: inset 0 0 0 1px var(--color-accent-ink);
  position: relative;
}

.kit-card.is-selected::after {
  content: "";
  position: absolute;
  top: -1px;
  right: -1px;
  width: 9px;
  height: 9px;
  border-top: 1px solid var(--color-accent);
  border-right: 1px solid var(--color-accent);
}

/* --- 11a. Legal documents --- */
/* The privacy policy and terms are long numbered texts. The global reset
   strips list indentation, and the source numbers its own clauses — "(1)",
   "①" — so markers stay off and a hanging indent lines the wrapped text up
   under the first character instead. */
.policy h2 {
  margin: 40px 0 12px;
  font-size: 1.125rem;
  line-height: 1.4;
}

.policy h3 {
  margin: 24px 0 8px;
  font-size: 0.97rem;
  line-height: 1.5;
  color: var(--ink);
}

.policy p {
  margin-bottom: 14px;
  font-size: 0.9rem;
  line-height: 1.85;
}

.policy ul {
  list-style: none;
  margin-bottom: 14px;
}

.policy li {
  margin-bottom: 6px;
  padding-left: 2.6em;
  text-indent: -2.6em;
  font-size: 0.9rem;
  line-height: 1.85;
  color: var(--ink-2);
}

.policy a {
  color: var(--color-accent-ink);
  text-decoration: underline;
  text-underline-offset: 2px;
  word-break: break-all;
}

.policy-meta {
  font-size: 0.8rem;
  color: var(--ink-3);
}

/* --- 11b. Company profile --- */
/* Label and value on a hairline grid, in the same register as the spec tables
   on the product sites. Rows still waiting on a value keep their height, so
   the block reads as a complete record with entries pending rather than as a
   broken layout. */
.company-facts {
  border-top: 1px solid var(--line);
}

.company-fact {
  display: grid;
  grid-template-columns: 12rem 1fr;
  gap: clamp(12px, 2vw, 32px);
  padding: 14px 0;
  border-bottom: 1px solid var(--line);
}

.company-fact dt {
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--ink-3);
}

.company-fact dd {
  margin: 0;
  min-height: 1.6em;
  font-size: 0.875rem;
  color: var(--ink);
}

@media (max-width: 560px) {
  .company-fact {
    grid-template-columns: 1fr;
    gap: 4px;
  }
}

/* --- 12. Cookie consent --- */
/* Injected by consent.js, so it exists only where JavaScript runs — which is
   also the only case where a cookie could be set. Sits above the sticky header
   (1000) and its dropdown (1001): until the visitor answers, this is the page. */
.consent-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1100;
  padding: 20px clamp(20px, 5vw, 64px);
  background-color: rgba(10, 10, 18, 0.97);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-top: 1px solid var(--color-accent);
}

.consent-inner {
  max-width: var(--container-max-width);
  margin-inline: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(20px, 3vw, 48px);
  flex-wrap: wrap;
}

.consent-copy {
  max-width: 74ch;
}

.consent-title {
  margin: 0 0 6px;
  font-size: 0.875rem;
  font-weight: 900;
  color: var(--ink);
}

.consent-body {
  margin: 0;
  font-size: 0.8rem;
  line-height: 1.6;
  color: var(--ink-3);
}

.consent-body a {
  color: var(--color-accent-ink);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.consent-actions {
  display: flex;
  gap: 12px;
  flex-shrink: 0;
}

/* The two answers are given the same size and prominence — a reject that is
   harder to reach than accept is not consent under the EU rules. */
.consent-actions .button {
  min-width: 150px;
}

@media (max-width: 700px) {

  .consent-actions {
    width: 100%;
  }

  .consent-actions .button {
    flex: 1;
    min-width: 0;
  }

}

/* The footer control that reopens the banner is a button, not a link. */
.consent-open {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  cursor: pointer;
}

/* --- 13. Reduced motion --- */
/* Anyone who has asked their OS to limit animation gets the same page with the
   movement taken out: transitions resolve instantly, the anchor jump stops
   smooth-scrolling, and the lift under the cursor on buttons and cards does
   not travel. Nothing is hidden and no layout changes — only the motion goes.
   Kept last so it wins over the component rules above it. */
@media (prefers-reduced-motion: reduce) {

  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  /* The hover lifts are the only decorative transforms on the site. */
  .button:hover,
.card-product:hover {
  transform: none !important;
  }

}

