/* ClassNet marketing site — assets/site-v2.css
   /assets/* is served immutable, so any change to this file must bump its name.
   Light mode only. Colour tokens are a deliberate copy of
   School-ERP/web/src/theme/tokens.ts; changing them is a two-repo decision.
   See CLAUDE.md §2. */

/* ── Inter ──────────────────────────────────────────────────────────── */
/* Self-hosted, because routing it through Google cost a render-blocking
   cross-origin stylesheet before anything could paint: HTML → googleapis CSS →
   gstatic woff2, three levels deep. Same-origin drops that to one hop.

   This is Google's own latin subset of the Inter v20 variable font, byte for
   byte — the exact file the CDN used to serve, so nothing about the typography
   changed. latin is the only subset Chrome ever fetched for this site; every
   rendered codepoint on all eight pages falls inside its unicode-range.

   To refresh it: request the css2 URL below with a modern browser UA, take the
   `latin` @font-face src, and bump the filename (see _headers — assets are
   immutable, so the name is the cache key).
     https://fonts.googleapis.com/css2?family=Inter:wght@400..800&display=swap

   400..800 is the full range the site uses: 400 body, 500, 600, 700 headings,
   800 h1. There is no italic anywhere, so there is no italic face to ship. */
@font-face {
  font-family: Inter;
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url(/assets/inter-latin-v20.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ── Tokens ─────────────────────────────────────────────────────────── */
:root {
  --brand-50:  #EFF4FF;
  --brand-100: #DCE7FF;
  --brand-200: #BDD0FE;
  --brand-600: #2563EB;
  --brand-700: #1D4ED8;
  --deep:      #23439D;
  /* No violet. The app's login gradient uses it, but on a calm teal-accented
     marketing page it is the one saturated colour with nothing to answer to. */

  /* The mark's teal. Emphasis is teal, action is blue — one rule, no exceptions. */
  --teal:      #7ACBC2;
  --teal-ink:  #0E6B60;
  --hl:        #CFEAE6;
  --hl-soft:   #E4F4F1;
  --hl-stroke: #4FB8AC;

  --page:      #F6F8FB;
  --card:      #FFFFFF;
  --ink:       #0B1220;
  /* Deliberate divergence from the product's text.secondary (#64748B): that value
     is 4.48:1 on this page background, just under WCAG AA. Darkened until it clears
     4.5 on both the page and card surfaces. See CLAUDE.md §2 — flagged for the app. */
  --ink-2:     #5A687E;
  --ink-3:     #97A3B6;  /* decorative only — fails AA on body copy */
  --line:      rgba(11, 18, 32, 0.08);
  --line-2:    rgba(11, 18, 32, 0.14);
  --hover:     rgba(11, 18, 32, 0.04);
  --on-brand:  #FFFFFF;
  --success:   #146C32;
  --danger:    #A81B1B;

  --r-sm: 9px;
  --r-md: 14px;
  --r-lg: 20px;
  --r-xl: 28px;
  --r-pill: 999px;

  --sh-1: 0 1px 2px rgba(11, 18, 32, 0.05);
  --sh-2: 0 1px 3px rgba(11, 18, 32, 0.09), 0 1px 2px -1px rgba(11, 18, 32, 0.06);
  --sh-3: 0 6px 14px -4px rgba(11, 18, 32, 0.10), 0 2px 5px -2px rgba(11, 18, 32, 0.05);
  --sh-5: 0 18px 34px -8px rgba(11, 18, 32, 0.13), 0 6px 12px -5px rgba(11, 18, 32, 0.05);
  --sh-6: 0 40px 70px -22px rgba(11, 18, 32, 0.26), 0 14px 26px -10px rgba(11, 18, 32, 0.08);

  /* Inter comes from Google Fonts with display=swap. If that request fails the
     stack below renders immediately and simply stays — no blank text. Nothing
     about the layout depends on Inter being present. */
  --font: Inter, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
    Arial, sans-serif;

  --container: 1440px;
  --gutter: 32px;
  --ease: 150ms ease;

  color-scheme: light;
}

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

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

body {
  margin: 0;
  font-family: var(--font);
  font-size: 1rem;
  line-height: 1.6;
  color: var(--ink);
  background: var(--page);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3, h4 {
  margin: 0; font-weight: 700; letter-spacing: -0.028em; line-height: 1.14;
  /* Stops a headline stranding one short word on its own line. An atomic .hl
     makes that likely, since the whole swipe jumps to the next line at once.
     Ignored by browsers that do not support it, which simply wrap as before. */
  text-wrap: balance;
}
h1 { font-size: clamp(2.75rem, 6.2vw, 5rem); font-weight: 800; }
/* An inline swipe paints the font's whole content area, which is taller than the
   1.14 line advance: on a two-line headline the box would sit on the descenders
   of the line above. Only headlines that carry one pay the extra leading. */
h1:has(.hl), h2:has(.hl) { line-height: 1.32; }
h2 { font-size: clamp(2rem, 3.8vw, 3rem); }
h3 { font-size: 1.25rem; letter-spacing: -0.015em; line-height: 1.3; }
h4 { font-size: 1rem; font-weight: 600; letter-spacing: -0.01em; }
p  { margin: 0; }

a { color: var(--brand-600); text-decoration: none; }
a:hover { text-decoration: underline; }
/* A link inside running text is underlined, so it is not told apart by colour alone. */
p a:not(.btn) { text-decoration: underline; text-underline-offset: 0.18em; text-decoration-thickness: 1px; }

img, svg { display: block; max-width: 100%; }
ul, ol { margin: 0; padding: 0; list-style: none; }

/* No border-radius here: the outline already follows each element's own corners,
   and setting one squared off every button and card the moment it took focus. */
:focus-visible { outline: 2px solid var(--brand-600); outline-offset: 2px; }

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  padding: 12px 20px; background: var(--card); color: var(--ink);
  border-radius: 0 0 var(--r-sm) 0; box-shadow: var(--sh-3); font-weight: 600;
}
.skip-link:focus { left: 0; }

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

/* ── Emphasis vocabulary ────────────────────────────────────────────── */
/* Three treatments, used sparingly. Emphasis is always teal so it never competes
   with a blue call to action. */

.hl {
  /* inline, so the box fragments per line and box-decoration-break: clone below
     gives each fragment its own swipe hugging its own text. An inline-block cannot
     fragment: it wraps internally and takes the full measure, which leaves the
     swipe running past the end of a short last line. */
  display: inline;
  background: var(--hl);
  border-radius: 14px;
  padding: 0.04em 0.26em;
  margin: 0 -0.06em;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
  /* The swipe reads as one gesture, so the phrase it covers stays on one line and
     moves to the next line whole. Released at 620px, where a long phrase at the
     headline size would otherwise overflow the viewport. */
  white-space: nowrap;
}

.mark {
  background: var(--hl-soft);
  border-radius: 6px;
  padding: 0.08em 0.3em;
  font-weight: 500;
  color: var(--ink);
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

/* Hand-drawn underline beneath a coloured phrase. Inline SVG, so no request. */
.u-stroke { position: relative; color: var(--teal-ink); white-space: nowrap; }
.u-stroke::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -0.16em; height: 0.17em;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 11' preserveAspectRatio='none'%3E%3Cpath d='M4 7.8C36 3.6 70 2.4 104 3.4c31 .9 61 2.8 92 4.6' fill='none' stroke='%234FB8AC' stroke-width='4.5' stroke-linecap='round'/%3E%3C/svg%3E") center/100% 100% no-repeat;
}

/* ── Layout ─────────────────────────────────────────────────────────── */
.container { width: 100%; max-width: var(--container); margin: 0 auto; padding: 0 var(--gutter); }

/* Escape the container and run to both viewport edges. Tinted bands use this so
   colour reaches the edge and the page stops reading as a column adrift in white. */
.bleed { width: 100vw; margin-inline: calc(50% - 50vw); }

.section { padding: 104px 0; }
.section--alt { background: var(--card); border-block: 1px solid var(--line); }
.section--tint { background: linear-gradient(180deg, #F1F7F6 0%, #F6F8FB 100%); }

.section-head { max-width: 780px; margin-bottom: 56px; }
.section-head--center { margin-inline: auto; text-align: center; }
.section-head p { margin-top: 18px; color: var(--ink-2); font-size: 1.0625rem; }

.eyebrow {
  display: inline-flex; align-items: center; gap: 8px; margin-bottom: 18px;
  font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--teal-ink);
}
.eyebrow::before {
  content: ""; width: 26px; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--deep), var(--teal));
}

.lede { font-size: 1.1875rem; line-height: 1.62; color: var(--ink-2); }

.badge {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 16px 7px 12px;
  background: var(--card); color: var(--teal-ink);
  border: 1px solid rgba(79, 184, 172, 0.34);
  border-radius: var(--r-pill);
  box-shadow: var(--sh-1);
  font-size: 0.8125rem; font-weight: 600;
}
.badge svg { color: var(--hl-stroke); }

/* ── Header ─────────────────────────────────────────────────────────── */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: rgba(246, 248, 251, 0.78);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border-bottom: 1px solid var(--line);
}
.site-header > .container { display: flex; align-items: center; gap: 24px; height: 72px; }

.brand {
  display: inline-flex; align-items: center; gap: 10px;
  color: var(--ink); font-weight: 700; font-size: 1.0625rem; letter-spacing: -0.02em;
}
.brand:hover { text-decoration: none; }
.brand img {
  width: 36px; height: 36px; padding: 4px;
  background: #FFFFFF; border-radius: 9px; box-shadow: var(--sh-2);
}

.nav { margin-left: auto; }
.nav ul { display: flex; align-items: center; gap: 2px; }
.nav a {
  display: block; padding: 9px 15px; border-radius: var(--r-sm);
  color: var(--ink-2); font-size: 0.9375rem; font-weight: 500;
  transition: background var(--ease), color var(--ease);
}
.nav a:hover { background: var(--hover); color: var(--ink); text-decoration: none; }
.nav a[aria-current="page"] { color: var(--ink); font-weight: 600; }
/* ...but not the CTA button: dark ink on the blue fill measures 3.45:1. */
.nav .btn, .nav .btn[aria-current="page"] { color: var(--on-brand); margin-left: 10px; }
.nav .btn:hover { background: var(--brand-700); color: var(--on-brand); }

.nav-toggle {
  display: none; margin-left: auto;
  width: 42px; height: 42px; padding: 0;
  align-items: center; justify-content: center;
  background: var(--card); border: 1px solid var(--line-2); border-radius: var(--r-sm);
  color: var(--ink); cursor: pointer;
}

/* ── Buttons ────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 11px 20px;
  border: 1px solid transparent; border-radius: var(--r-sm);
  font-family: inherit; font-size: 0.9375rem; font-weight: 600; line-height: 1.4;
  cursor: pointer; white-space: nowrap;
  transition: background var(--ease), border-color var(--ease), color var(--ease),
              box-shadow var(--ease), transform var(--ease);
}
.btn:hover { text-decoration: none; }
.btn svg { flex-shrink: 0; transition: transform var(--ease); }
.btn--primary {
  background: var(--brand-600); color: var(--on-brand);
  box-shadow: 0 1px 2px rgba(11, 18, 32, 0.12), 0 6px 16px -6px rgba(37, 99, 235, 0.55);
}
.btn--primary:hover { background: var(--brand-700); transform: translateY(-1px); }
.btn--primary:hover svg { transform: translateX(3px); }
.btn--ghost { background: var(--card); border-color: var(--line-2); color: var(--ink); box-shadow: var(--sh-1); }
.btn--ghost:hover { background: var(--card); border-color: var(--ink-3); transform: translateY(-1px); }
.btn--lg { padding: 15px 28px; font-size: 1rem; border-radius: 11px; }
.btn[disabled] { opacity: 0.55; cursor: not-allowed; transform: none; }

.btn-row { display: flex; flex-wrap: wrap; gap: 12px; }

/* ── Cards & grids ──────────────────────────────────────────────────── */
.card { background: var(--card); border: 1px solid var(--line); border-radius: var(--r-md); box-shadow: var(--sh-2); }
.card--pad { padding: 30px; }
.card--pad h3 { margin-bottom: 10px; }
.card--pad p { color: var(--ink-2); font-size: 0.9375rem; }

.grid { display: grid; gap: 20px; }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }

/* ── Hero ───────────────────────────────────────────────────────────── */
.hero { position: relative; padding: 64px 0 96px; overflow: hidden; text-align: center; }

/* Dot grid + a teal glow. Both are gradients, so they cost nothing. */
.hero::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image: radial-gradient(circle, rgba(11, 18, 32, 0.06) 1px, transparent 1px);
  background-size: 24px 24px;
  mask-image: radial-gradient(ellipse 90% 58% at 50% 24%, #000 34%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 90% 58% at 50% 24%, #000 34%, transparent 78%);
}
.hero::after {
  content: ""; position: absolute; z-index: 0; pointer-events: none;
  top: -320px; left: 50%; width: 1100px; height: 700px; transform: translateX(-50%);
  background: radial-gradient(ellipse at center, rgba(122, 203, 194, 0.30), transparent 64%);
}
.hero > .container { position: relative; z-index: 1; }

.hero h1 { margin: 26px auto 0; max-width: 17ch; }
.hero .lede { max-width: 58ch; margin: 26px auto 0; font-size: 1.25rem; }
.hero .btn-row { justify-content: center; margin-top: 36px; }
.hero .trust { margin-top: 18px; color: var(--ink-2); font-size: 0.875rem; }

/* The three surfaces the product ships on. Stated as badges rather than buried in
   a sentence, because "does it have an app" is a question every school asks. */
.platforms {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 10px;
  margin-top: 22px;
}
.platform {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 10px 18px;
  /* Tinted, matching the hero badge. Plain white pills read as diagram nodes,
     which sit a few hundred pixels below and would be confused with these. */
  background: var(--hl-soft); border: 1px solid rgba(79, 184, 172, 0.34);
  border-radius: var(--r-pill);
  color: var(--teal-ink);
  font-size: 0.875rem; font-weight: 600; white-space: nowrap;
}
.platform svg { color: var(--teal-ink); flex-shrink: 0; }

.hero-proof {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 10px 30px;
  margin-top: 28px; color: var(--ink-2); font-size: 0.875rem; font-weight: 500;
}
/* Interior pages wear the same hero band as the home page — dot grid, teal glow,
   centred stack — so /modules and /about open the way / does. They carry no
   diagram stage below it, hence the shorter bottom padding. */
.hero--page { padding: 56px 0 76px; }
/* A notch under the home headline: the same face and weight, sized so an interior
   page reads as a chapter of the site rather than a second front door. */
.hero--page h1 { font-size: clamp(2.5rem, 4.6vw, 3.75rem); max-width: 20ch; }
.hero--page .lede { font-size: 1.125rem; }
.hero--page .platforms { margin-top: 32px; }

/* The module pills double as jump links on /modules. */
a.platform { color: var(--teal-ink); }
a.platform:hover { text-decoration: none; background: var(--hl); border-color: var(--hl-stroke); }

.hero-proof li { display: flex; align-items: center; gap: 8px; }
.hero-proof svg { flex-shrink: 0; color: var(--hl-stroke); }

/* ── Hero diagram ──────────────────────────────────────────── */
/* Deliberately NOT a picture of the product. A mocked-up dashboard misrepresents
   a UI we would then have to keep in sync with every release; this describes the
   architecture instead, which is the actual differentiator and cannot go stale.
   Wider than the text container on purpose — the diagram is what sets the page
   sense of width and stops the content reading as a stranded column. */
.hero-stage {
  position: relative; z-index: 1;
  width: min(1440px, 94vw);
  margin: 40px auto 0;
  aspect-ratio: 2.7 / 1;
}

/* Concentric rings, echoing the network graph in the ClassNet mark. */
.hero-stage::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(circle at 50% 50%, transparent 20.6%, rgba(79,184,172,0.26) 21%, transparent 21.5%),
    radial-gradient(circle at 50% 50%, transparent 32.6%, rgba(79,184,172,0.18) 33%, transparent 33.5%),
    radial-gradient(circle at 50% 50%, transparent 44.6%, rgba(79,184,172,0.11) 45%, transparent 45.5%);
}

/* The spokes share the node coordinate space, so they align exactly at any
   width; non-scaling-stroke keeps them hairline when the box is stretched. */
.hero-stage__links { position: absolute; inset: 0; width: 100%; height: 100%; }
.hero-stage__links line {
  stroke: #9AD5CD; stroke-width: 1.5; vector-effect: non-scaling-stroke;
}

.hub {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  z-index: 2; display: flex; align-items: center; gap: 13px;
  padding: 17px 26px 17px 19px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: 0 24px 48px -16px rgba(11,18,32,0.24), 0 0 0 10px rgba(246,248,251,0.85);
  white-space: nowrap;
}
.hub img { width: 40px; height: 40px; }
/* Ink set explicitly: the strong sits inside a span, so `.hub span` below would grey it. */
.hub strong { display: block; font-size: 1.0625rem; letter-spacing: -0.022em; color: var(--ink); }
.hub span { display: block; font-size: 0.8125rem; color: var(--ink-2); }

.node {
  position: absolute; transform: translate(-50%, -50%); z-index: 1;
  display: inline-flex; align-items: center; gap: 9px;
  padding: 10px 17px 10px 13px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-pill); box-shadow: var(--sh-2);
  font-size: 0.875rem; font-weight: 600; white-space: nowrap;
}
.node svg { color: var(--teal-ink); flex-shrink: 0; }

/* Seven nodes on an ellipse around the hub. */
.node:nth-of-type(1) { left: 16%; top: 23%; }
.node:nth-of-type(2) { left: 40%; top: 8%; }
.node:nth-of-type(3) { left: 67%; top: 11%; }
.node:nth-of-type(4) { left: 86%; top: 34%; }
.node:nth-of-type(5) { left: 81%; top: 78%; }
.node:nth-of-type(6) { left: 50%; top: 92%; }
.node:nth-of-type(7) { left: 18%; top: 71%; }

/* ── Marquee — a full-bleed band of capabilities ────────────────────── */
.marquee {
  overflow: hidden; padding: 22px 0;
  background: var(--card); border-block: 1px solid var(--line);
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.marquee__track { display: flex; width: max-content; animation: marquee 46s linear infinite; }
.marquee ul { display: flex; align-items: center; gap: 14px; padding-right: 14px; }
.marquee li {
  display: flex; align-items: center; gap: 9px;
  padding: 9px 18px; border: 1px solid var(--line);
  border-radius: var(--r-pill); background: var(--page);
  font-size: 0.875rem; font-weight: 500; white-space: nowrap; color: var(--ink-2);
}
.marquee li::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--hl-stroke); flex-shrink: 0;
}
@keyframes marquee { to { transform: translateX(-50%); } }

/* ── Bento grid ─────────────────────────────────────────────────────── */
/* Seven equal cards read as a spec sheet. Varying the spans gives the eye a
   path through them and lets the two anchor modules carry a visual. */
.bento { display: grid; grid-template-columns: repeat(6, 1fr); gap: 20px; }
.bento > * { grid-column: span 2; }
.bento > .is-wide { grid-column: span 3; }

.tile {
  display: flex; flex-direction: column; gap: 11px;
  padding: 28px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--sh-2); color: inherit;
  transition: transform 180ms ease, box-shadow 180ms ease, border-color var(--ease);
}
a.tile:hover {
  transform: translateY(-3px); box-shadow: var(--sh-5);
  border-color: var(--line-2); text-decoration: none;
}
.tile__icon {
  display: grid; place-items: center;
  width: 44px; height: 44px; border-radius: 12px;
  background: var(--hl-soft); color: var(--teal-ink);
}
.tile h3 { font-size: 1.125rem; }
.tile p { color: var(--ink-2); font-size: 0.9375rem; }
.tile__more {
  margin-top: auto; padding-top: 6px;
  font-size: 0.875rem; font-weight: 600; color: var(--brand-600);
  display: inline-flex; align-items: center; gap: 6px;
}
a.tile:hover .tile__more svg { transform: translateX(3px); }
.tile__more svg { transition: transform var(--ease); }

/* A miniature visual inside the two wide tiles. */
.tile__viz {
  margin-top: 6px; padding: 14px;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--page);
}
.viz-row {
  display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 10px;
  padding: 7px 0; font-size: 0.8125rem;
}
.viz-row + .viz-row { border-top: 1px solid var(--line); }
.viz-grid { display: grid; grid-template-columns: repeat(14, 1fr); gap: 4px; }
.viz-grid i { aspect-ratio: 1; border-radius: 3px; background: #CDEBD8; }
.viz-grid i.is-absent { background: #F6D2D2; }
.viz-grid i.is-empty { background: var(--hover); }
/* A row of the product's real status chips, in the order a record moves through them. */
.viz-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.viz-chips .pill { font-size: 0.75rem; padding: 4px 11px; }
.viz-chips svg { color: var(--ink-3); flex-shrink: 0; }

.pill { display: inline-block; padding: 3px 11px; border-radius: var(--r-pill); font-size: 0.6875rem; font-weight: 600; }
.pill--ok { background: #E3F3E9; color: var(--success); }
.pill--brand { background: var(--brand-50); color: var(--brand-600); }
.pill--teal { background: var(--hl-soft); color: var(--teal-ink); }
.pill--muted { background: var(--hover); color: var(--ink-2); }

/* ── Numbered steps ─────────────────────────────────────────────────── */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; counter-reset: step; }
.step { position: relative; padding-top: 26px; }
.step::before {
  counter-increment: step; content: counter(step, decimal-leading-zero);
  display: block; margin-bottom: 14px;
  font-size: 0.8125rem; font-weight: 700; letter-spacing: 0.08em; color: var(--hl-stroke);
}
.step::after {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background: var(--line-2);
}
.step:first-child::after { background: linear-gradient(90deg, var(--deep), var(--teal)); }
.step h3 { margin-bottom: 9px; }
.step p { color: var(--ink-2); font-size: 0.9375rem; }

/* ── Module detail sections ─────────────────────────────────────────── */
.module { padding: 84px 0; border-top: 1px solid var(--line); scroll-margin-top: 84px; }
.module > .container { display: grid; grid-template-columns: 1fr 1fr; gap: 72px; align-items: center; }
/* Alternating bands, the same rhythm the home page sections have, so seven rows
   read as chapters instead of one long scroll. */
.module:nth-of-type(even) { background: var(--card); }
.module:nth-of-type(even) .module__media { order: -1; }
.module h2 { font-size: clamp(1.75rem, 2.8vw, 2.25rem); margin-bottom: 18px; }
.module > .container > div > p { color: var(--ink-2); margin-bottom: 24px; font-size: 1.0625rem; }

.feature-list { display: grid; gap: 14px; }
.feature-list li { display: flex; gap: 12px; align-items: flex-start; font-size: 0.9375rem; }
.feature-list svg { flex-shrink: 0; margin-top: 4px; color: var(--hl-stroke); }

/* Module-page mockups. */
.mock {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--sh-5); overflow: hidden; text-align: left;
}
/* A panel header the way the console draws one: a title and a quiet caption, not
   a fake window with traffic-light dots. */
.mock__bar {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 20px;
  border-bottom: 1px solid var(--line);
}
.mock__title { font-size: 0.875rem; font-weight: 600; color: var(--ink); letter-spacing: -0.01em; }
.mock__meta { font-size: 0.75rem; color: var(--ink-2); white-space: nowrap; }
.mock__body { padding: 20px; display: grid; gap: 14px; }

.mock-kpis { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.mock-kpi { padding: 14px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--page); }
.mock-kpi span {
  display: block; font-size: 0.6875rem; font-weight: 600;
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--ink-2);
}
.mock-kpi strong { display: block; margin-top: 4px; font-size: 1.25rem; letter-spacing: -0.03em; }

.mock-rows { display: grid; gap: 9px; }
.mock-row {
  display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 12px;
  padding: 11px 13px; border: 1px solid var(--line); border-radius: var(--r-sm); font-size: 0.8125rem;
}
.mock-row b { font-weight: 600; }
.mock-row small { display: block; font-size: 0.75rem; color: var(--ink-2); }
/* Tabular figures so a column of numbers lines up the way it does in the console. */
.mock-kpi strong, .mock-row .num { font-variant-numeric: tabular-nums; }
.mock-row .num { color: var(--ink-2); font-size: 0.8125rem; }

.mock-attendance { display: grid; grid-template-columns: repeat(10, 1fr); gap: 5px; }
.mock-attendance i { aspect-ratio: 1; border-radius: 3px; background: #CDEBD8; }
.mock-attendance i.is-absent { background: #F6D2D2; }
.mock-attendance i.is-empty { background: var(--hover); }

/* ── FAQ ────────────────────────────────────────────────────────────── */
.faq { display: grid; gap: 12px; max-width: 840px; margin-inline: auto; }
.faq details {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-md); box-shadow: var(--sh-1);
  transition: box-shadow var(--ease), border-color var(--ease);
}
.faq details[open] { box-shadow: var(--sh-3); border-color: var(--line-2); }
.faq summary {
  display: flex; justify-content: space-between; align-items: center; gap: 16px;
  padding: 20px 24px; font-weight: 600; cursor: pointer; list-style: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; flex-shrink: 0; width: 9px; height: 9px;
  border-right: 2px solid var(--ink-2); border-bottom: 2px solid var(--ink-2);
  transform: rotate(45deg) translateY(-3px);
  transition: transform 180ms ease;
}
.faq details[open] summary::after { transform: rotate(-135deg) translateY(-1px); }
.faq .faq__a { padding: 0 24px 22px; color: var(--ink-2); }

/* ── Closing CTA ────────────────────────────────────────────────────── */
/* A contained panel, not a full-bleed saturated band. The band version was the
   only heavily saturated surface on the site and read as a different product. */
.cta-section { padding: 48px 0 104px; }
.cta-panel {
  position: relative; overflow: hidden;
  padding: 88px 40px; text-align: center;
  background: linear-gradient(165deg, #EDF7F5 0%, #EAF1FF 100%);
  border: 1px solid var(--line);
  border-radius: 32px;
}
.cta-panel::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: radial-gradient(circle, rgba(11, 18, 32, 0.06) 1px, transparent 1px);
  background-size: 24px 24px;
  mask-image: radial-gradient(ellipse 66% 78% at 50% 50%, transparent 28%, #000 100%);
  -webkit-mask-image: radial-gradient(ellipse 66% 78% at 50% 50%, transparent 28%, #000 100%);
}
.cta-panel > * { position: relative; z-index: 1; }
.cta-panel h2 { margin: 0 auto 18px; max-width: 24ch; }
.cta-panel p { max-width: 54ch; margin: 0 auto 34px; color: var(--ink-2); font-size: 1.0625rem; }
.cta-panel .btn-row { justify-content: center; }

/* ── Forms ──────────────────────────────────────────────────────────── */
.form { display: grid; gap: 18px; }
/* align-content keeps rows at their natural height: inside a .field-row the
   columns stretch, and a field with a hint would otherwise make its neighbour's
   input grow to match. */
.field { display: grid; gap: 6px; align-content: start; }
.field label { font-size: 0.875rem; font-weight: 600; }
/* The asterisk is a glyph, not a colour cue: the colour is emphasis only, and
   `required` on the input is what actually reaches assistive tech. */
.req { color: var(--danger); font-weight: 700; }
.field .hint { font-size: 0.8125rem; color: var(--ink-2); }
.field input, .field select, .field textarea {
  width: 100%; padding: 12px 14px;
  font-family: inherit; font-size: 0.9375rem; color: var(--ink);
  background: var(--card); border: 1px solid var(--line-2); border-radius: var(--r-sm);
  transition: border-color var(--ease), box-shadow var(--ease);
}
.field textarea { min-height: 120px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--brand-600);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.18);
}
.field [aria-invalid="true"] { border-color: var(--danger); }
.field .error { font-size: 0.8125rem; color: var(--danger); }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }

/* Phone is India-only, so the country code is furniture, not an input: a fixed
   +91 sits inside the control and the box itself takes the 10 national digits.
   The border and focus ring move to the wrapper so the pair reads as one field. */
.tel-group {
  display: flex; align-items: stretch;
  background: var(--card); border: 1px solid var(--line-2); border-radius: var(--r-sm);
  transition: border-color var(--ease), box-shadow var(--ease);
}
.tel-prefix {
  display: flex; align-items: center; padding: 0 10px 0 14px;
  font-size: 0.9375rem; color: var(--ink-2);
  border-right: 1px solid var(--line-2);
}
.tel-group input { flex: 1; min-width: 0; border: 0; background: none; }
.tel-group input:focus { box-shadow: none; }
.tel-group:focus-within {
  border-color: var(--brand-600); box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.18);
}

/* Honeypot — off-screen rather than display:none, which some bots skip. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form-status { padding: 14px 16px; border-radius: var(--r-sm); font-size: 0.9375rem; }
.form-status--ok { background: #E3F3E9; color: var(--success); }
.form-status--err { background: #FBE9E9; color: var(--danger); }

.contact-grid { display: grid; grid-template-columns: 1.15fr 1fr; gap: 72px; align-items: start; }
.contact-detail { display: grid; gap: 4px; padding: 18px 0; border-bottom: 1px solid var(--line); }
.contact-detail:last-child { border-bottom: 0; }
.contact-detail dt {
  font-size: 0.75rem; font-weight: 600; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--ink-2);
}
.contact-detail dd { margin: 0; font-size: 1rem; }

/* ── Prose (privacy / terms) ────────────────────────────────────────── */
.prose { max-width: 760px; margin-inline: auto; }
.prose h1 { font-size: clamp(2rem, 4vw, 2.75rem); }
.prose h2 { font-size: 1.375rem; margin: 44px 0 12px; }
.prose h3 { font-size: 1.0625rem; margin: 28px 0 8px; }
.prose p, .prose li { color: var(--ink-2); margin-bottom: 12px; }
.prose ul { list-style: disc; padding-left: 22px; margin-bottom: 16px; }
.prose > p:first-of-type { font-size: 1.0625rem; }

/* ── Footer ─────────────────────────────────────────────────────────── */
.site-footer { padding: 64px 0 30px; background: var(--card); border-top: 1px solid var(--line); }
.footer-top { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 48px; margin-bottom: 44px; }
.footer-top p { margin-top: 14px; max-width: 34em; color: var(--ink-2); font-size: 0.9375rem; }
.footer-by { margin-top: 14px; font-size: 0.9375rem; color: var(--ink-2); }
.footer-by a { color: var(--ink); font-weight: 600; }

.site-footer h2 {
  font-size: 0.75rem; font-weight: 600; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--ink-2); margin-bottom: 16px;
}
.site-footer nav ul { display: grid; gap: 11px; }
.site-footer nav a { color: var(--ink-2); font-size: 0.9375rem; }
.site-footer nav a:hover { color: var(--ink); }
.footer-bottom {
  display: flex; flex-wrap: wrap; gap: 8px 20px; justify-content: space-between;
  padding-top: 26px; border-top: 1px solid var(--line);
  color: var(--ink-2); font-size: 0.8125rem;
}

/* ── Responsive ─────────────────────────────────────────────────────── */
@media (max-width: 1100px) {
  .bento { grid-template-columns: repeat(4, 1fr); }
  .bento > *, .bento > .is-wide { grid-column: span 2; }
  .hero-stage { width: min(100%, 96vw); }
}

@media (max-width: 900px) {
  :root { --gutter: 20px; }
  .section { padding: 72px 0; }
  .hero { padding: 52px 0 0; }
  .hero-stage {
    aspect-ratio: auto; width: 100%; margin: 36px auto 0;
    display: flex; flex-direction: column; align-items: center; gap: 16px;
  }
  .hero-stage::before, .hero-stage__links { display: none; }
  .hub, .node { position: static; transform: none; }
  .hub { order: -1; box-shadow: var(--sh-5); }
  .hero-stage .node-cluster { display: flex; flex-wrap: wrap; justify-content: center; gap: 9px; }
  .steps { grid-template-columns: 1fr; gap: 20px; }
  .module > .container,
  .contact-grid { grid-template-columns: 1fr; gap: 44px; }
  .module:nth-of-type(even) .module__media { order: 0; }
  .grid--3, .grid--2 { grid-template-columns: repeat(2, 1fr); }
  .footer-top { grid-template-columns: 1fr 1fr; }
  .cta-panel { padding: 64px 26px; border-radius: 24px; }
  .cta-section { padding: 28px 0 72px; }

  .nav-toggle { display: inline-flex; }
  .nav {
    display: none; position: absolute; left: 0; right: 0; top: 72px;
    padding: 12px var(--gutter) 22px;
    background: var(--page); border-bottom: 1px solid var(--line); box-shadow: var(--sh-3);
  }
  .nav[data-open="true"] { display: block; }
  .nav ul { flex-direction: column; align-items: stretch; gap: 2px; }
  .nav a { padding: 13px 15px; font-size: 1rem; }
  .nav .btn { margin: 10px 0 0; }
}

@media (max-width: 620px) {
  .bento, .grid--3, .grid--2, .field-row { grid-template-columns: 1fr; }
  .bento > *, .bento > .is-wide { grid-column: auto; }
  .footer-top { grid-template-columns: 1fr; gap: 30px; }
  .mock-kpis { grid-template-columns: 1fr 1fr; }
  .btn-row .btn { width: 100%; }
  .mock__body { padding: 16px; }
  .hero h1 { max-width: none; }
  /* A nowrap highlighted or underlined phrase can force a scrollbar on a narrow screen. */
  .hl, .u-stroke { white-space: normal; }
}

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