/* ==========================================================================
   Tenrix Cloud Transformations — public website

   Shares the console's identity so the site and the product read as one
   company: the same dark ground, the same green, the same mono for anything
   the machine said. What differs is the display face — Fraunces, a
   high-contrast serif — because a page set entirely in Inter is every other
   technology site, and an engineering firm that migrates banks should not look
   like a template someone filled in.

   **Fluid throughout.** No fixed breakpoints deciding what a layout looks
   like: type scales with `clamp()`, columns are `auto-fit` with a minimum, and
   gutters grow with the viewport. A page that snaps between three layouts has
   three chances to look wrong; one that flows has none.
   ========================================================================== */

:root {
  --ink: #0A0D0C;
  --ink-soft: #0E1211;
  --surface: #121614;
  --surface-raised: #171C1A;
  --line: #222A27;
  --line-soft: #1A201E;

  --text: #E9EEEB;
  --text-muted: #96A19D;
  --text-dim: #626C69;

  --green: #33D296;
  --green-bright: #4FE6AC;
  --green-deep: #0E3A2A;
  --green-wash: rgba(51, 210, 150, 0.08);

  /* The second accent, used sparingly: a warm brass against all that green,
     for the one number or mark that should catch the eye on a page. */
  --brass: #E0A94A;
  --brass-wash: rgba(224, 169, 74, 0.10);

  /* One colour per product silo in the Hyper-vSOC picture. Chosen to be
     distinct from one another *and* from the platform green, which is reserved
     for "correlated": the moment the colours stop being separate silos and
     become one incident. The canvas reads these same tokens, so the legend and
     the drawing cannot disagree about which colour is which. */
  --silo-identity: #5B9DFF;
  --silo-endpoint: #FF7A59;
  --silo-email:    #B48CFF;
  --silo-network:  #F2B84B;
  --silo-cloud:    #F06DAA;

  --display: 'Fraunces', 'Iowan Old Style', Georgia, serif;
  --sans: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;

  /* Fluid type. Each step scales between a phone and a wide desktop, so there
     is no width at which the page is "between" sizes. */
  --step--1: clamp(0.78rem, 0.74rem + 0.18vw, 0.87rem);
  --step-0:  clamp(0.95rem, 0.90rem + 0.24vw, 1.06rem);
  --step-1:  clamp(1.15rem, 1.05rem + 0.45vw, 1.42rem);
  --step-2:  clamp(1.45rem, 1.25rem + 0.95vw, 2.10rem);
  --step-3:  clamp(1.95rem, 1.55rem + 1.85vw, 3.20rem);
  --step-4:  clamp(2.45rem, 1.75rem + 3.30vw, 4.90rem);

  /* Fluid rhythm: the space between sections grows with the page. */
  --gap: clamp(1rem, 0.7rem + 1.4vw, 2rem);
  --section: clamp(3.5rem, 2.2rem + 6vw, 8rem);
  --gutter: clamp(1.15rem, 0.6rem + 4vw, 5rem);
  /* The sticky header's height. Declared once because the mobile sheet is
     positioned against it, and two clamps drifting apart leaves a gap or an
     overlap that only shows at certain widths. */
  --header-h: clamp(62px, 52px + 1.8vw, 92px);

  --radius: 12px;
  --radius-lg: 18px;
}

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

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

body.site {
  margin: 0;
  background: var(--ink);
  color: var(--text);
  font-family: var(--sans);
  font-size: var(--step-0);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

img { max-width: 100%; display: block; }
a { color: inherit; }

/* The one container rule. Side padding is set here and nowhere else, so no
   element can lose its gutter by overriding a shorthand. */
.wrap {
  width: 100%;
  max-width: 1320px;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.wrap-wide { max-width: 1560px; }

/* --- type ---------------------------------------------------------------- */

h1, h2, h3 {
  font-family: var(--display);
  font-weight: 500;
  font-optical-sizing: auto;
  line-height: 1.08;
  letter-spacing: -0.015em;
  text-wrap: balance;
  margin: 0;
}

h1 { font-size: var(--step-4); }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-1); font-weight: 600; letter-spacing: -0.005em; }

p { margin: 0 0 1em; max-width: 68ch; }

.eyebrow {
  font-family: var(--mono);
  font-size: var(--step--1);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--green);
  margin: 0 0 clamp(0.8rem, 0.5rem + 0.8vw, 1.4rem);
}

.lede { font-size: var(--step-1); color: var(--text-muted); line-height: 1.5; }
.muted { color: var(--text-muted); }
.dim { color: var(--text-dim); }

/* --- navigation ---------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: rgba(10, 13, 12, 0.82);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line-soft);
}

.site-header-inner {
  display: flex;
  align-items: center;
  gap: var(--gap);
  /* Starts at 62px rather than 76: a sticky header is permanent furniture, and
     on a 667px-tall phone every pixel it takes is one the page never gets. */
  min-height: var(--header-h);
}

.brand {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  flex: 0 0 auto;
}

/* Sized by height so the lockup keeps its own proportions at any viewport —
   a logo with a fixed width is one that squashes the moment the header does. */
.brand-mark {
  height: clamp(34px, 26px + 1.9vw, 56px);
  width: auto;
}
.brand-mark-footer {
  height: clamp(56px, 46px + 1.6vw, 76px);
  margin-bottom: 1rem;
}

/* Kept for the mobile panel and anywhere the wordmark is still set in type. */
.brand-dot { color: var(--green); }
.brand-sub {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.site-nav { display: flex; align-items: center; gap: 0.15rem; margin-left: auto; }

.nav-item { position: relative; }

.nav-link {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.55rem 0.85rem;
  border-radius: 8px;
  font-size: 0.925rem;
  color: var(--text-muted);
  text-decoration: none;
  white-space: nowrap;
  background: none;
  border: 0;
  font-family: inherit;
  cursor: pointer;
  transition: color .15s ease, background .15s ease;
}
.nav-link:hover, .nav-link:focus-visible { color: var(--text); background: var(--surface); }
.nav-link[aria-current="page"] { color: var(--text); }
.nav-link svg { opacity: .6; transition: transform .18s ease; }
.nav-item:hover .nav-link svg,
.nav-item:focus-within .nav-link svg { transform: rotate(180deg); }

/* The dropdown. Opens on hover and on keyboard focus — a menu that only
   answers a mouse is one a keyboard user cannot reach at all. */
.dropdown {
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  translate: -50% 0;
  min-width: min(560px, 82vw);
  padding: 0.75rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: 0 24px 60px rgba(0, 0, 0, .55);
  opacity: 0;
  visibility: hidden;
  translate: -50% 6px;
  transition: opacity .16s ease, translate .16s ease, visibility .16s;
}
.nav-item:hover > .dropdown,
.nav-item:focus-within > .dropdown {
  opacity: 1;
  visibility: visible;
  translate: -50% 0;
}

/* With a preview, the panel becomes two columns: links on the left, image on
   the right. Without one it stays a plain grid, so a group that has no preview
   does not leave a gap where a picture should be. */
.dropdown.has-preview {
  min-width: min(760px, 88vw);
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.85fr);
  gap: 0.75rem;
}

.dropdown-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 0.35rem;
  align-content: start;
}
.dropdown.has-preview .dropdown-grid { grid-template-columns: 1fr; }

.dropdown-preview {
  position: relative;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid var(--line-soft);
  min-height: 100%;
  display: flex;
  align-items: flex-end;
  isolation: isolate;
}
.dropdown-preview img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -2;
}
/* The photograph is a ground for the sentence, so it is darkened enough that
   the text is legible whatever the image happens to be. */
.dropdown-preview::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(190deg, rgba(10,13,12,.28), rgba(10,13,12,.9));
  z-index: -1;
}
.dropdown-preview p {
  margin: 0;
  padding: 0.95rem 1rem;
  font-size: 0.83rem;
  line-height: 1.5;
  color: var(--text-muted);
}

/* Narrow viewports: the preview would squeeze the links, so it goes. */
@media (max-width: 1080px) {
  .dropdown.has-preview { grid-template-columns: 1fr; min-width: min(420px, 88vw); }
  .dropdown-preview { display: none; }
}

.dropdown-link {
  display: flex;
  gap: 0.7rem;
  padding: 0.7rem 0.75rem;
  border-radius: 10px;
  text-decoration: none;
  transition: background .14s ease;
}
.dropdown-link:hover, .dropdown-link:focus-visible { background: var(--surface-raised); }

.dropdown-mark {
  flex: 0 0 auto;
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border-radius: 9px;
  background: var(--green-wash);
  border: 1px solid rgba(51, 210, 150, .18);
  color: var(--green);
  font-family: var(--mono);
  font-size: 0.64rem;
  font-weight: 500;
}
.dropdown-name { font-size: 0.925rem; line-height: 1.3; }
.dropdown-note { font-size: 0.79rem; color: var(--text-dim); line-height: 1.45; }

.soon {
  font-family: var(--mono);
  font-size: 0.6rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--brass);
  border: 1px solid rgba(224, 169, 74, .3);
  border-radius: 4px;
  padding: 0.05rem 0.3rem;
  margin-left: 0.4rem;
  vertical-align: 1px;
}

/* --- buttons ------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.72rem 1.25rem;
  border-radius: 9px;
  font-size: 0.93rem;
  font-weight: 500;
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, translate .15s ease;
  white-space: nowrap;
}
.btn:hover { translate: 0 -1px; }
.btn-primary { background: var(--green); color: #05140E; font-weight: 600; }
.btn-primary:hover { background: var(--green-bright); }
.btn-ghost { border-color: var(--line); color: var(--text); }
.btn-ghost:hover { border-color: var(--green); background: var(--green-wash); }
.btn-sm { padding: 0.5rem 0.9rem; font-size: 0.86rem; }

/* --- hero ---------------------------------------------------------------- */

.hero { position: relative; overflow: hidden; padding-block: var(--section); }

/* A single wash rather than a gradient across the whole page: the eye should
   settle on the headline, not on the background doing something. */
.hero::before {
  content: "";
  position: absolute;
  inset: -30% 40% 30% -20%;
  background: radial-gradient(closest-side, rgba(51, 210, 150, .10), transparent);
  pointer-events: none;
}

.hero-grid {
  position: relative;
  display: grid;
  gap: clamp(2rem, 1rem + 4vw, 4.5rem);
  grid-template-columns: repeat(auto-fit, minmax(min(420px, 100%), 1fr));
  align-items: center;
}

.hero h1 { margin-bottom: clamp(1rem, .6rem + 1.2vw, 1.8rem); }
.hero .lede { max-width: 54ch; }

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: clamp(1.4rem, 1rem + 1.4vw, 2.2rem);
}

.hero-figure {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--line);
  /* Sized by the panel inside it rather than by a fixed ratio: four rows fit a
     wide screen and a phone alike, where a 4:3 frame cut the last of them off
     at any width narrower than a laptop. The photograph is only the backdrop. */
  display: grid;
  min-height: clamp(440px, 38vw, 620px);
  max-width: 100%;
}
.hero-figure img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
}

/* The image is a photograph of people, not of software — so it is tinted
   toward the brand rather than left as a stock rectangle. */
.hero-figure::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(200deg, rgba(10,13,12,.15), rgba(10,13,12,.78));
}

.ok { color: var(--green); }

/* --- sections ------------------------------------------------------------ */

.section { padding-block: var(--section); }
.section-tight { padding-block: calc(var(--section) * .62); }
.section-line { border-top: 1px solid var(--line-soft); }

.section-head { margin-bottom: clamp(2rem, 1.2rem + 2.4vw, 3.6rem); }
.section-head p { max-width: 62ch; }

/* --- cards --------------------------------------------------------------- */

.grid {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
}
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(min(420px, 100%), 1fr)); }
.grid-tight { gap: clamp(.6rem, .4rem + .6vw, 1rem); }

.card {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  padding: clamp(1.15rem, .8rem + 1.2vw, 1.8rem);
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-lg);
  text-decoration: none;
  transition: border-color .18s ease, background .18s ease, translate .18s ease;
}
a.card:hover {
  border-color: rgba(51, 210, 150, .34);
  background: var(--surface-raised);
  translate: 0 -2px;
}

.card-mark {
  width: 42px; height: 42px;
  display: grid; place-items: center;
  border-radius: 10px;
  background: var(--green-wash);
  border: 1px solid rgba(51, 210, 150, .18);
  color: var(--green);
  font-family: var(--mono);
  font-size: 0.7rem;
}
.card h3 { margin: 0; }
.card p { margin: 0; font-size: 0.92rem; color: var(--text-muted); }

.card-more {
  margin-top: auto;
  padding-top: 0.3rem;
  font-size: 0.86rem;
  color: var(--green);
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}
a.card:hover .card-more { gap: 0.6rem; }
.card-more span { transition: gap .18s ease; }

/* --- proof strip --------------------------------------------------------- */

.proof {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr));
}
.proof-item { border-left: 2px solid var(--green-deep); padding-left: 1.1rem; }
.proof-item b {
  display: block;
  font-family: var(--display);
  font-size: var(--step-2);
  font-weight: 500;
  letter-spacing: -0.02em;
}
.proof-item span { font-size: 0.9rem; color: var(--text-muted); }

/* --- partners ------------------------------------------------------------ */

.partner-grid {
  display: grid;
  gap: clamp(.55rem, .4rem + .5vw, .9rem);
  grid-template-columns: repeat(auto-fill, minmax(min(250px, 100%), 1fr));
}

.partner {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding: 0.95rem 1.1rem;
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
}

.partner-mark {
  flex: 0 0 auto;
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: 9px;
  color: #fff;
  font-family: var(--mono);
  font-size: 0.68rem;
  font-weight: 500;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.14);
}
.partner-name { font-size: 0.92rem; line-height: 1.3; }
.partner-role { font-size: 0.78rem; color: var(--text-dim); line-height: 1.4; }

.pill {
  display: inline-flex;
  align-items: center;
  gap: 0.32rem;
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 0.16rem 0.5rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--text-dim);
}
.pill-live { color: var(--green); border-color: rgba(51,210,150,.3); background: var(--green-wash); }
.pill-soon { color: var(--brass); border-color: rgba(224,169,74,.3); background: var(--brass-wash); }

/* --- references ---------------------------------------------------------- */

.ref {
  padding: clamp(1.15rem, .8rem + 1.2vw, 1.7rem);
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-lg);
}
.ref-name { font-family: var(--display); font-size: var(--step-1); font-weight: 600; }
.ref-meta {
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-block: .3rem .8rem;
}
.ref p { margin: 0; font-size: .92rem; color: var(--text-muted); }

.notice {
  border: 1px dashed rgba(224, 169, 74, .35);
  background: var(--brass-wash);
  border-radius: var(--radius);
  padding: clamp(.9rem, .7rem + .8vw, 1.3rem);
  font-size: .9rem;
  color: var(--text-muted);
}
.notice strong { color: var(--brass); }

/* --- solution page ------------------------------------------------------- */

.page-hero { position: relative; padding-block: var(--section) calc(var(--section) * .55); }
.page-hero h1 { margin-bottom: clamp(.8rem, .5rem + 1vw, 1.3rem); }

.figure-wide {
  margin-top: clamp(1.8rem, 1rem + 2.6vw, 3rem);
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--line);
  position: relative;
  aspect-ratio: 21 / 9;
}
.figure-wide img { width: 100%; height: 100%; object-fit: cover; }
.figure-wide::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(10,13,12,.1), rgba(10,13,12,.62));
}

.split {
  display: grid;
  gap: clamp(1.6rem, 1rem + 3vw, 4rem);
  grid-template-columns: repeat(auto-fit, minmax(min(360px, 100%), 1fr));
}

.list-check { list-style: none; margin: 0; padding: 0; display: grid; gap: .8rem; }
.list-check li {
  display: flex;
  gap: .7rem;
  font-size: .95rem;
  color: var(--text-muted);
  line-height: 1.55;
}
.list-check svg { flex: 0 0 auto; margin-top: .3rem; color: var(--green); }

.callout {
  border-left: 2px solid var(--green);
  padding: .2rem 0 .2rem 1.3rem;
}
.callout p:last-child { margin-bottom: 0; }

/* --- footer -------------------------------------------------------------- */

.site-footer {
  border-top: 1px solid var(--line-soft);
  padding-block: var(--section) 2.5rem;
  background: var(--ink-soft);
}
.footer-grid {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
  margin-bottom: clamp(2rem, 1.4rem + 2vw, 3.5rem);
}
.footer-title {
  font-family: var(--mono);
  font-size: .68rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: .9rem;
}
.footer-links { display: grid; gap: .5rem; }
.footer-links a {
  font-size: .9rem;
  color: var(--text-muted);
  text-decoration: none;
  transition: color .14s ease;
}
.footer-links a:hover { color: var(--green); }

.footer-base {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  justify-content: space-between;
  align-items: center;
  padding-top: 1.8rem;
  border-top: 1px solid var(--line-soft);
  font-size: .82rem;
  color: var(--text-dim);
}

/* --- cta ----------------------------------------------------------------- */

.cta {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  border: 1px solid rgba(51, 210, 150, .2);
  background:
    radial-gradient(120% 140% at 12% 0%, rgba(51,210,150,.13), transparent 62%),
    var(--surface);
  padding: clamp(2rem, 1.2rem + 3.4vw, 4rem);
  text-align: center;
}
.cta h2 { margin-bottom: .9rem; }
.cta p { margin-inline: auto; }
.cta .hero-actions { justify-content: center; }

/* --- small screens ------------------------------------------------------- */

/* Hidden by default and shown at the breakpoint. Declared *before* the media
   query on purpose: same specificity means source order decides, so a base
   rule written afterwards would silently win and hide the menu everywhere. */
.nav-mobile { display: none; }

/* The only breakpoint in the file, and it changes behaviour rather than
   layout: below this the dropdowns become inline lists, because a hover menu
   on a touch screen is a menu that cannot be opened. */
@media (max-width: 860px) {
  .site-nav { display: none; }
  .nav-mobile { display: block; }
}

/* --- phones -------------------------------------------------------------
   Below this the design stops being a narrow desktop and starts being a phone
   layout: buttons go full width because a 44px-tall button floating in a
   360px row reads as an afterthought, and the type scale stops shrinking. */
@media (max-width: 600px) {
  /* Buttons side by side on a phone are two half-width targets and a wrap that
     puts one alone on a line. Stacked and full-width is one clear action each. */
  .hero-actions,
  .band-actions { flex-direction: column; align-items: stretch; }
  .hero-actions .btn,
  .band-actions .btn { width: 100%; min-height: 48px; }

  .btn { min-height: 46px; }

  /* A sticky header plus a hero sized for a laptop leaves nothing visible. */
  .hero { padding-block: clamp(2.2rem, 1.4rem + 4vw, 3.4rem); }
  .page-hero { padding-block: clamp(2rem, 1.2rem + 4vw, 3rem) clamp(1.2rem, 1rem + 2vw, 2rem); }

  /* 54ch of measure on a 360px screen is not a constraint, it is a no-op that
     leaves the text hugging both edges. */
  .hero .lede, .lede { max-width: none; }

  /* Tables and anything wider than the screen scroll in their own box rather
     than making the whole page scroll sideways. */
  table { display: block; overflow-x: auto; }
}

/* Never let the page itself scroll sideways, whatever a child does. */
html, body { overflow-x: hidden; }

/* `display` for this element is set in the breakpoint above, not here — a base
   `display:none` written after that media query wins on source order and the
   menu never appears at any width. */
.nav-mobile { margin-left: auto; }

/* The icon swaps with the disclosure's own state — no script, same as the menu. */
.nav-mobile .menu-close { display: none; }
.nav-mobile[open] .menu-open { display: none; }
.nav-mobile[open] .menu-close { display: inline; }

/* "Talk to us" stays on the bar at phone width. The one action the site exists
   to get is not worth burying two taps deep behind a menu. */
.header-cta { display: none; }
@media (max-width: 860px) {
  .header-cta {
    display: inline-flex;
    margin-left: auto;
    min-height: 40px;
  }
  .header-cta + .nav-mobile { margin-left: .5rem; }
}
@media (max-width: 380px) {
  /* Below this the two of them start fighting the logo. The menu wins — it
     contains the CTA anyway. */
  .header-cta { display: none; }
}

.nav-mobile summary {
  list-style: none;
  cursor: pointer;
  /* 44px minimum: the smallest thing a finger hits reliably. A 0.55rem-padded
     button is comfortable with a cursor and a near-miss with a thumb. */
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .5rem .9rem;
  border: 1px solid var(--line);
  border-radius: 9px;
  color: var(--text-muted);
  font-size: .95rem;
  -webkit-tap-highlight-color: transparent;
}
.nav-mobile summary::-webkit-details-marker { display: none; }
.nav-mobile[open] summary { color: var(--text); border-color: var(--green); }

.nav-mobile-panel {
  position: fixed;
  left: 0;
  right: 0;
  /* Anchored under the header rather than floated below the button: a panel
     positioned relative to the button drifts with it, and on a short screen the
     bottom of the list ends up past the fold with nothing to scroll. */
  top: var(--header-h);
  padding: 1rem var(--gutter) calc(1rem + env(safe-area-inset-bottom));
  background: var(--surface);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 24px 60px rgba(0,0,0,.55);
  z-index: 70;
  /* dvh, not vh: mobile browsers count the collapsing address bar in vh, so a
     70vh panel is taller than the screen until the user scrolls. */
  max-height: calc(100dvh - var(--header-h));
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Tap targets inside the sheet, and a layout that does not try to be a grid on
   a 360px screen. */
.nav-mobile-panel .dropdown-grid { grid-template-columns: 1fr; gap: .15rem; }
.nav-mobile-panel .dropdown-link { padding: .7rem .6rem; min-height: 48px; align-items: center; }
.nav-mobile-panel .footer-links {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .2rem;
}
.nav-mobile-panel .footer-links a {
  display: flex;
  align-items: center;
  min-height: 46px;
  padding: .4rem .6rem;
  border-radius: 9px;
}
.nav-mobile-panel .footer-links a:hover,
.nav-mobile-panel .footer-links a:focus-visible { background: var(--surface-raised); }

/* The sheet is open: stop the page behind it scrolling under the finger. */
.nav-mobile[open] { position: static; }


/* --- correlation field ---------------------------------------------------
   The Hyper-vSOC picture: five product silos, each its own colour and each
   seeing only its own corner, then signals from three of them pointing at the
   same person and a line joining them into one incident. The claim, drawn
   rather than described. Taller than it was, because the silos need room for
   their labels and the story needs room for its captions. */

.field {
  position: relative;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  background:
    radial-gradient(90% 120% at 18% 0%, rgba(51,210,150,.06), transparent 60%),
    var(--ink-soft);
  overflow: hidden;
  min-height: clamp(400px, 36vw, 560px);
  display: grid;
}
.field canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
/* On a phone the five silos stack in three rows and the legend wraps to two
   lines, so the picture needs more height than the fluid clamp gives it. */
@media (max-width: 640px) {
  .field { min-height: 480px; }
}

.field-legend {
  position: relative;
  align-self: end;
  display: flex;
  flex-wrap: wrap;
  gap: clamp(.7rem, .4rem + .9vw, 1.6rem);
  padding: clamp(.9rem, .6rem + 1vw, 1.4rem);
  font-family: var(--mono);
  font-size: .68rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.field-legend span { display: inline-flex; align-items: center; gap: .42rem; }
.field-legend i {
  width: 8px; height: 8px; border-radius: 50%; display: inline-block;
}
/* The incident swatch is the one that glows: it is the only thing in the
   picture that is not a silo. */
.field-legend i.legend-incident {
  background: var(--green-bright);
  box-shadow: 0 0 0 3px rgba(51, 210, 150, .22);
}

/* --- capability rows -----------------------------------------------------
   Deliberately not cards. A grid of equal rounded boxes with an icon, a bold
   line and two lines of grey is the single most recognisable generated-site
   pattern; this is a numbered list with a rule between each, which reads as a
   document rather than a template. */

.rows { display: grid; gap: 0; }

.row-item {
  display: grid;
  gap: clamp(.5rem, .3rem + 1vw, 2.5rem);
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  padding-block: clamp(1.4rem, 1rem + 1.6vw, 2.4rem);
  border-top: 1px solid var(--line-soft);
  align-items: start;
}
.row-item:last-child { border-bottom: 1px solid var(--line-soft); }

.row-index {
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .12em;
  color: var(--green);
  padding-top: .35rem;
}
.row-item h3 { margin-bottom: .45rem; }
.row-item p { margin: 0; color: var(--text-muted); font-size: .95rem; }

/* --- closing band --------------------------------------------------------
   Replaces the centred gradient panel. That shape — rounded box, wash behind,
   heading, one grey line, two buttons — is on every generated site there is.
   This is a full-bleed band with the type on the left and the action on the
   right, which is how a firm's own site closes a page. */

.band {
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
  background: var(--ink-soft);
}
.band-inner {
  display: grid;
  gap: clamp(1.2rem, .8rem + 2vw, 3rem);
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  align-items: center;
  padding-block: clamp(2.6rem, 1.8rem + 3.4vw, 4.6rem);
}
.band h2 { font-size: var(--step-2); margin-bottom: .6rem; }
.band p { margin: 0; color: var(--text-muted); max-width: 46ch; }
.band-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  justify-content: flex-start;
}
@media (min-width: 900px) {
  .band-actions { justify-content: flex-end; }
}

/* --- area blocks (home) --------------------------------------------------
   One per area of the business, built the same way. Migration used to be the
   only one with a proper introduction; security and modernisation were a card
   each. Copy on one side, a photograph on the other, alternating so the page
   does not read as the same panel three times. Fluid: `auto-fit` with a
   minimum, so it stacks on a phone without a breakpoint deciding when. */

.area {
  display: grid;
  gap: clamp(1.6rem, 1rem + 3.4vw, 4.5rem);
  grid-template-columns: repeat(auto-fit, minmax(min(380px, 100%), 1fr));
  align-items: center;
}
.area-flip .area-copy { order: 2; }
.area-flip .area-media { order: 1; }
/* Stacked, the copy always comes first, whichever way round it sits beside the
   picture on a wide screen. */
@media (max-width: 820px) {
  .area-flip .area-copy, .area-flip .area-media { order: 0; }
}

.area h2 { font-size: var(--step-3); margin-bottom: 1rem; }

.area-media {
  margin: 0;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--line);
  position: relative;
  aspect-ratio: 4 / 3;
}
.area-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.area-media::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(10,13,12,.05), rgba(10,13,12,.5));
}

.area-links {
  list-style: none;
  margin: clamp(1.4rem, 1rem + 1.2vw, 2rem) 0 0;
  padding: 0;
  display: grid;
  gap: .55rem;
}
.area-links a {
  display: flex;
  align-items: center;
  gap: .95rem;
  padding: .8rem 1rem;
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  text-decoration: none;
  color: var(--text);
  transition: border-color .18s ease, background .18s ease, translate .18s ease;
}
.area-links a:hover, .area-links a:focus-visible {
  border-color: rgba(51, 210, 150, .34);
  background: var(--surface-raised);
  translate: 2px 0;
}
.area-links .card-mark { flex: 0 0 auto; width: 40px; height: 40px; }
.area-link-text { display: grid; gap: .1rem; min-width: 0; flex: 1 1 auto; }
.area-link-text b { font-size: .96rem; font-weight: 600; line-height: 1.3; }
.area-link-text small { font-size: .82rem; color: var(--text-muted); line-height: 1.4; }
.area-links svg { flex: 0 0 auto; color: var(--green); }

/* --- how it runs ---------------------------------------------------------
   A numbered sequence, said from the customer's side: what they are asked,
   what they can watch, what they receive. A rule across the top of each step
   carries the eye along the order without arrows or a fake progress bar. */

.steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(1.2rem, .8rem + 1.6vw, 2.2rem);
  grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr));
  counter-reset: none;
}
.step { border-top: 2px solid var(--green-deep); padding-top: 1rem; }
.step:first-child { border-top-color: var(--green); }
.step-num {
  display: block;
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .12em;
  color: var(--green);
  margin-bottom: .55rem;
}
.step h3 { margin: 0 0 .4rem; font-size: var(--step-1); }
.step p { margin: 0; font-size: .92rem; color: var(--text-muted); line-height: 1.55; }

/* --- worth knowing up front ---------------------------------------------- */

.boundaries { margin: .6rem 0 0; padding-left: 1.1rem; display: grid; gap: .35rem; }
.boundaries li { color: var(--text-muted); line-height: 1.55; }

/* --- the 3D engagement panel (hero) ---------------------------------------
   What a customer would actually see: every source counted, checked, and the
   things that did not move named rather than hidden. Tilted in perspective,
   with each row floating at its own depth so it reads as layers rather than a
   flat list, and following the pointer a few degrees. `ledger.js` plays it: the
   numbers count up, the bars fill, each status flips from "verifying" to
   "verified". The markup is the finished state, so with scripts off or reduced
   motion it is simply the result. */

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

.ledger-stage {
  position: relative;
  z-index: 2;
  display: grid;
  place-items: center;
  padding: clamp(1.6rem, 1rem + 2.6vw, 3rem) clamp(1.2rem, .6rem + 2.4vw, 2.6rem);
  perspective: 1300px;
}

.ledger {
  --rx: 9deg;
  --ry: -14deg;
  width: min(100%, 430px);
  display: grid;
  gap: clamp(.5rem, .3rem + .6vw, .8rem);
  transform-style: preserve-3d;
  transform: rotateX(var(--rx)) rotateY(var(--ry)) rotateZ(.6deg);
  transition: transform .35s cubic-bezier(.2, .7, .2, 1);
  font-family: var(--mono);
  font-size: clamp(.64rem, .6rem + .2vw, .74rem);
  /* `translate` is its own property, so the gentle float does not fight the
     tilt the script sets on `transform`. */
  animation: ledger-float 7s ease-in-out infinite;
}
@keyframes ledger-float {
  0%, 100% { translate: 0 -4px; }
  50%      { translate: 0 5px; }
}

.ledger-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: .4rem .95rem;
  color: var(--text);
  letter-spacing: .12em;
  text-transform: uppercase;
  font-size: .9em;
  background: rgba(10, 13, 12, .82);
  border: 1px solid rgba(60, 74, 69, .7);
  border-radius: 999px;
  transform: translateZ(78px);
  box-shadow: 0 16px 26px -14px rgba(0, 0, 0, .8);
}
.ledger-tag { display: inline-flex; align-items: center; gap: .45rem; color: var(--text-muted); }
.ledger-tag i {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--green);
  box-shadow: 0 0 0 0 rgba(51, 210, 150, .5);
  animation: ledger-ping 2.2s ease-out infinite;
}
@keyframes ledger-ping {
  0%   { box-shadow: 0 0 0 0 rgba(51, 210, 150, .5); }
  80%, 100% { box-shadow: 0 0 0 8px rgba(51, 210, 150, 0); }
}

.ledger-row {
  position: relative;
  padding: clamp(.6rem, .45rem + .5vw, .8rem) clamp(.8rem, .6rem + .6vw, 1rem) clamp(.7rem, .5rem + .55vw, .9rem);
  background: linear-gradient(160deg, rgba(26, 32, 30, .97), rgba(13, 17, 16, .97));
  border: 1px solid rgba(60, 74, 69, .7);
  border-radius: var(--radius);
  transform: translateZ(var(--z, 0px));
  box-shadow:
    0 26px 34px -20px rgba(0, 0, 0, .85),
    0 2px 0 rgba(255, 255, 255, .04) inset;
  overflow: hidden;
}
/* A slow sheen across each layer, staggered, so the stack catches the light one
   after another. */
.ledger-row::before {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 38%, rgba(255, 255, 255, .07) 50%, transparent 62%);
  background-size: 260% 100%;
  background-position: 130% 0;
  animation: ledger-sheen 7s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * .9s);
  pointer-events: none;
}
@keyframes ledger-sheen {
  0%, 55%  { background-position: 130% 0; }
  100%     { background-position: -30% 0; }
}

.ledger-top { display: flex; justify-content: space-between; align-items: center; gap: .8rem; }
.ledger-src {
  color: var(--text-muted);
  letter-spacing: .1em;
  text-transform: uppercase;
  font-size: .92em;
}

.ledger-figure { display: flex; align-items: baseline; gap: .55rem; margin: .25rem 0 .5rem; }
.ledger-count {
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(1.3rem, 1.05rem + .95vw, 1.8rem);
  line-height: 1;
  letter-spacing: -.02em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.ledger-unit { color: var(--text-dim); }

/* The chip flips in when its state changes, like a card being turned over. */
.ledger-status {
  --c: var(--green);
  perspective: 300px;
  display: inline-flex;
}
.ledger-status-text {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .18rem .6rem;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--c) 45%, transparent);
  background: color-mix(in srgb, var(--c) 12%, transparent);
  color: var(--c);
  white-space: nowrap;
  transform-origin: 50% 50%;
  animation: ledger-flip .5s cubic-bezier(.2, .8, .2, 1) both;
}
@keyframes ledger-flip {
  from { transform: rotateX(-90deg); opacity: 0; }
  to   { transform: rotateX(0);      opacity: 1; }
}
.ledger-status[data-state="verified"] .ledger-status-text::before {
  content: "";
  width: .55em; height: .3em;
  border-left: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  transform: rotate(-45deg) translate(1px, -1px);
  margin-right: .1rem;
}
.ledger-status[data-state="checking"] { --c: var(--brass); }
.ledger-status[data-state="checking"] .ledger-status-text::before,
.ledger-status[data-state="counting"] .ledger-status-text::before {
  content: "";
  width: .7em; height: .7em;
  border: 1.5px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: ledger-spin .8s linear infinite;
}
.ledger-status[data-state="counting"] { --c: var(--text-muted); }
.ledger-status[data-state="copying"] { --c: var(--green-bright); }
.ledger-status[data-state="named"] { --c: var(--brass); }
@keyframes ledger-spin { to { transform: rotate(360deg); } }

.ledger-track {
  height: 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .07);
  overflow: hidden;
}
.ledger-fill {
  display: block;
  height: 100%;
  width: var(--p, 0%);
  border-radius: inherit;
  background: linear-gradient(90deg, var(--green-deep), var(--green) 70%, var(--green-bright));
  box-shadow: 0 0 14px rgba(51, 210, 150, .55);
  transition: width 1.5s cubic-bezier(.2, .7, .2, 1);
}
/* The one that is still moving carries a running stripe. */
.ledger-fill.is-live {
  background:
    repeating-linear-gradient(115deg, rgba(255,255,255,.22) 0 6px, transparent 6px 12px),
    linear-gradient(90deg, var(--green-deep), var(--green) 70%, var(--green-bright));
  background-size: 24px 100%, 100% 100%;
  animation: ledger-run 1s linear infinite;
}
@keyframes ledger-run { to { background-position: 24px 0, 0 0; } }

/* Not migrated: brass rather than green, because it is the row that should be
   read, not skimmed. One mark per item — every one of them is in the report. */
.ledger-row.is-named { border-color: rgba(224, 169, 74, .4); border-style: dashed; }
.ledger-dots { display: flex; gap: .4rem; }
.ledger-dots i {
  width: 14px; height: 6px; border-radius: 3px;
  background: var(--brass);
  box-shadow: 0 0 10px rgba(224, 169, 74, .45);
  opacity: 1;
  transform: scaleX(1);
  transform-origin: left;
  transition: opacity .3s ease, transform .3s ease;
}
.ledger-dots i.is-off { opacity: 0; transform: scaleX(.2); }

@media (prefers-reduced-motion: reduce) {
  .ledger, .ledger-row::before, .ledger-tag i, .ledger-fill.is-live { animation: none !important; }
  .ledger-status-text { animation: none; }
}

/* A gentler tilt on a phone, where the panel is nearly as wide as the screen and
   a steep angle would push its outer edge past the frame. */
@media (max-width: 640px) {
  .ledger { --rx: 6deg; --ry: -8deg; }
}
