/* Claspex landing page.
   RULE, same as the styleguide: not a single hex value in this file.
   Every colour, size, space and radius resolves through tokens.css
   layer 2. If something here needs a value with no token, the token is
   missing — add it to tokens.css rather than inlining it.

   Rules this file is deliberately obeying:
   - Blue is interactive only. No blue headings, no blue rules, no blue
     as decoration. Check every --color-action use below: all are links,
     buttons or focus.
   - Indigo is type and dark surfaces. Never a button fill.
   - Selvedge red does not appear. It has no layer 2 token on purpose.
   - No shadows, no gradients. Depth is surface steps and hairlines.
   - Mono with tabular-nums for anything countable. */


/* ---------- motion ----------

   Three animations on this page and no more:
     1. in-page nav scrolls instead of jumping
     2. content rises 8px as it enters the viewport, once
     3. buttons and links respond to hover and press

   Everything else is still. The reveal is deliberately one-way —
   scrolling back up does not replay it, because a section that
   re-animates every pass reads as a page that has lost its place.

   The reveal is opt-in from script: markup carries [data-reveal],
   but nothing is hidden until reveal.js adds .js-reveal to <html>.
   No script, an old browser, or a reduced-motion reader all get
   the page fully visible. Hiding content in CSS and relying on JS
   to bring it back is how a marketing page ships blank. */

html { scroll-behavior: smooth; }

/* An anchored section should not start flush against the top of
   the viewport. */
[id] { scroll-margin-top: var(--space-6); }

.js-reveal [data-reveal] {
  opacity: 0;
  transform: translateY(var(--motion-rise));
}

.js-reveal [data-reveal].is-in {
  opacity: 1;
  transform: none;
  transition: opacity var(--duration-slow) var(--ease-out),
              transform var(--duration-slow) var(--ease-out);
  /* Siblings arrive in sequence. --reveal-index is set by script
     per sibling group and capped, so the sixth card is not still
     waiting when the reader has moved on. */
  transition-delay: calc(var(--reveal-index, 0) * var(--motion-stagger));
}


/* ---------- layout shell ---------- */

.shell {
  max-width: var(--page-max);
  margin-inline: auto;
  padding-inline: var(--space-5);
}

@media (min-width: 1100px) {
  .shell { padding-inline: var(--space-6); }
}

.band { padding-block: var(--space-8); }

/* Alternating surface step is how sections separate. No shadow, no rule. */
.band-alt { background: var(--color-surface-card); }

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

/* Slides on transform, not on `top`. Animating a layout property
   costs a reflow per frame, and this one fires on the very first
   Tab press of the page. */
.skip-link {
  position: absolute;
  left: var(--space-3);
  top: var(--space-3);
  z-index: 10;
  padding: var(--space-2) var(--space-4);
  background: var(--color-action);
  color: var(--color-on-action);
  border-radius: var(--radius);
  font-size: var(--text-label);
  text-decoration: none;
  transform: translateY(calc(-100% - var(--space-5)));
  transition: transform var(--duration-fast) var(--ease-out);
}

.skip-link:focus { transform: translateY(0); }


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

.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-eyebrow);
  line-height: var(--leading-eyebrow);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--color-text-secondary);
  margin: 0 0 var(--space-3);
}

.display-l {
  font-size: var(--text-display-l);
  line-height: var(--leading-display-l);
  letter-spacing: var(--tracking-tight);
  font-weight: var(--weight-bold);
  color: var(--color-text-primary);
  margin: 0 0 var(--space-4);
  max-width: 18ch;
}

.display-s {
  font-size: var(--text-display-s);
  line-height: var(--leading-display-s);
  letter-spacing: var(--tracking-tight);
  font-weight: var(--weight-bold);
  color: var(--color-text-primary);
  margin: 0 0 var(--space-3);
  max-width: 26ch;
}

/* --color-text-secondary, never --color-text-muted: this is body copy the
   reader must actually read, and muted measures 3.11:1. */
.lede {
  font-size: var(--text-title);
  line-height: var(--leading-body);
  color: var(--color-text-secondary);
  max-width: 58ch;
  margin: 0 0 var(--space-5);
}

.section-lede {
  color: var(--color-text-secondary);
  max-width: 62ch;
  margin: 0 0 var(--space-6);
}

.section-lede strong {
  color: var(--color-text-primary);
  font-weight: var(--weight-bold);
}


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

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--control-height);
  padding: 0 var(--space-5);
  border: var(--border-width) solid transparent;
  border-radius: var(--radius);
  font-family: var(--font-sans);
  font-size: var(--text-label);
  font-weight: var(--weight-medium);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out),
              transform var(--duration-instant) var(--ease-out);
}

/* Press moves the button 1px down and gets there in 80ms. Any
   slower and the button appears to lag the finger. There is no
   shadow to remove, so the nudge is the whole of the feedback. */
.btn:active { transform: translateY(var(--motion-press)); }

.btn-lg {
  height: calc(var(--control-height) + var(--space-2));
  padding: 0 var(--space-6);
  font-size: var(--text-body);
}

.btn-primary {
  background: var(--color-action);
  color: var(--color-on-action);
}
.btn-primary:hover { background: var(--color-action-hover); }
.btn-primary:active { background: var(--color-action-pressed); }

.btn-secondary {
  background: var(--color-surface-card);
  color: var(--color-text-primary);
  border-color: var(--color-border-strong);
}
.btn-secondary:hover { background: var(--color-surface-sunken); }

.btn-ghost {
  background: transparent;
  color: var(--color-text-secondary);
}
.btn-ghost:hover { background: var(--color-surface-sunken); }

.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

/* A CTA following a card grid needs its own air, or it reads as a
   sixth card. */
.card-grid + .cta-row { margin-top: var(--space-6); }


/* ---------- header ---------- */

.site-head {
  background: var(--color-surface-card);
  border-bottom: var(--border-width) solid var(--color-border);
}

.head-inner {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  height: calc(var(--control-height) + var(--space-5));
}

/* ---------- lockup ----------

   Every measurement derives from --lockup-icon so the proportions in
   logo/README.md cannot drift: gap is a third of the icon height,
   wordmark is two thirds, clearspace is half. Nothing here is a
   free-standing number.

   The wordmark is Medium (500), not Bold — the logo spec is explicit
   and the previous text-only mark had it at 600.

   NOTE for whoever owns the brand files: claspex-lockup-*.svg is
   authored on a 292x72 canvas, which implies the wordmark advances
   292-96 = 196 units. Measured in IBM Plex Sans Medium at 48px with
   -15/1000 tracking it advances ~170. The source SVGs therefore
   carry ~27 units of empty space on the right edge, and anything
   that centres or right-aligns those files will sit visibly off.
   This CSS lockup is built from live text so it is unaffected, but
   the SVG canvases should be re-cropped in round 2. */

.lockup {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--lockup-icon) / 3);
  color: var(--color-text-primary);
  text-decoration: none;
  margin: 0;
}

.lockup-mark {
  width: var(--lockup-icon);
  height: var(--lockup-icon);
  flex: none;
  overflow: visible;
}

.lockup-word {
  font-size: calc(var(--lockup-icon) * 2 / 3);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-wordmark);
  line-height: 1;
}

/* Clearspace: half the icon height on all four sides. In the header
   the row gap already provides more than that to the right. */
.head-inner .lockup { margin-inline-end: calc(var(--lockup-icon) / 2); }

/* Draw-on, header only. One mark animating per page load is a
   signature; two is a habit, so the footer lockup stays still.

   The resting state is DRAWN — the keyframe runs from the undrawn
   state towards it. That ordering is what makes every failure mode
   safe: no CSS animation support, reduced motion, or a stylesheet
   that never arrives all leave a complete logo rather than an
   invisible one. */
@keyframes lockup-draw {
  from { stroke-dashoffset: 100; }
  to   { stroke-dashoffset: 0; }
}

.site-head .lockup-mark path {
  stroke-dasharray: 100;      /* = pathLength, so no gap when drawn */
  stroke-dashoffset: 0;
  animation: lockup-draw var(--duration-base) var(--ease-out) both;
}

/* The second ring waits until the first is half drawn. Sequence is
   the whole point — the mark is two rings interlocking, and drawn
   simultaneously they read as one shape appearing. */
.site-head .lockup-mark path:nth-child(2) {
  animation-delay: calc(var(--duration-base) / 2);
}

.head-nav {
  display: flex;
  gap: var(--space-5);
  margin-inline-start: var(--space-4);
}

.head-nav a {
  font-size: var(--text-label);
  color: var(--color-text-secondary);
  text-decoration: none;
  transition: color var(--duration-fast) var(--ease-out);
}
.head-nav a:hover { color: var(--color-action); }

.head-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-inline-start: auto;
}


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

.hero {
  padding-block: var(--space-8) var(--space-8);
}

.hero-note {
  font-size: var(--text-label);
  color: var(--color-text-secondary);
  margin: 0;
}


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

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--space-4);
  list-style: none;
  padding: 0;
  margin: 0;
}

.card-grid-3 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }

.card {
  background: var(--color-surface-card);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius);
  padding: var(--space-5);
}

/* On a dark band the card sits on the raised indigo step, and .on-dark has
   already remapped every token this rule reads. */
.on-dark .card {
  background: var(--color-surface-card);
  border-color: var(--color-border);
}

.card-title {
  font-size: var(--text-title);
  line-height: var(--leading-title);
  font-weight: var(--weight-medium);
  color: var(--color-text-primary);
  margin: 0 0 var(--space-2);
}

.card p,
.step p {
  color: var(--color-text-secondary);
  margin: 0;
}


/* ---------- steps ---------- */

.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: var(--space-5) var(--space-6);
  list-style: none;
  padding: 0;
  margin: 0;
}

.step {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-4);
  align-items: start;
  padding-top: var(--space-4);
  border-top: var(--border-width) solid var(--color-border);
}

/* Countable, so mono. Secondary, not blue — a step number is not
   interactive. */
.step-num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-label);
  font-weight: var(--weight-medium);
  color: var(--color-text-secondary);
}


/* ---------- quote table — the trust section ---------- */

.quote {
  background: var(--color-surface-card);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius);
  padding: var(--space-5);
  max-width: 860px;
}

.quote-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}

.quote-eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-eyebrow);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--color-text-secondary);
  margin: 0 0 var(--space-1);
}

.quote-title {
  font-size: var(--text-title);
  font-weight: var(--weight-medium);
  color: var(--color-text-primary);
  margin: 0;
}

.table-wrap { overflow-x: auto; }

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-label);
}

.table thead th {
  background: var(--color-surface-sunken);
  color: var(--color-text-secondary);
  font-family: var(--font-mono);
  font-size: var(--text-eyebrow);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  text-align: left;
  padding: var(--space-3) var(--space-4);
  border-bottom: var(--border-width) solid var(--color-border);
}

.table tbody th,
.table tfoot th {
  text-align: left;
  font-weight: var(--weight-medium);
  color: var(--color-text-primary);
}

.table tbody td,
.table tbody th,
.table tfoot td,
.table tfoot th {
  padding: var(--space-3) var(--space-4);
  border-bottom: var(--border-width) solid var(--color-border);
  vertical-align: baseline;
}

.table tfoot td,
.table tfoot th {
  border-bottom: none;
  border-top: var(--border-width) solid var(--color-border-strong);
  padding-top: var(--space-4);
}

.calc { color: var(--color-text-secondary); }

.num { text-align: right; }

.mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
  color: var(--color-text-primary);
}

.total {
  font-size: var(--text-title);
  font-weight: var(--weight-bold);
}

.quote-foot {
  font-size: var(--text-label);
  color: var(--color-text-secondary);
  margin: var(--space-5) 0 0;
  max-width: 62ch;
}

/* Status colour never carries meaning alone — the pill has a text label. */
.pill {
  display: inline-block;
  font-size: var(--text-eyebrow);
  font-weight: var(--weight-medium);
  line-height: var(--leading-label);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  white-space: nowrap;
  margin: 0;
}

.pill[data-tone='verified'] {
  background: var(--color-verified-bg);
  color: var(--color-on-verified);
}


/* ---------- origin ---------- */

.origin .display-s { max-width: 30ch; }


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

/* .on-dark remaps the semantic layer; this overrides only the surface so
   the footer sits a step deeper than the maker band. */
.site-foot {
  background: var(--color-surface-darkest);
  padding-block: var(--space-8) var(--space-5);
}

.foot-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  gap: var(--space-6);
  padding-bottom: var(--space-7);
}

.foot-brand .lockup { display: flex; margin-bottom: var(--space-2); }

.tagline {
  font-size: var(--text-label);
  color: var(--color-text-secondary);
  margin: 0;
}

.foot-nav {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--space-5);
}

.foot-head {
  font-family: var(--font-mono);
  font-size: var(--text-eyebrow);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin: 0 0 var(--space-3);
}

/* The underline is always drawn, just transparent, so it can fade
   in. Toggling text-decoration itself is not animatable and the
   rule pops. */
.foot-nav a {
  display: block;
  font-size: var(--text-label);
  color: var(--color-text-primary);
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 0.2em;
  margin-bottom: var(--space-2);
  transition: text-decoration-color var(--duration-fast) var(--ease-out);
}
.foot-nav a:hover { text-decoration-color: currentColor; }

.foot-legal {
  border-top: var(--border-width) solid var(--color-border);
  padding-top: var(--space-4);
}

.foot-legal p {
  font-size: var(--text-label);
  color: var(--color-text-secondary);
  margin: 0;
}


/* ---------- responsive ---------- */

@media (max-width: 860px) {
  .head-nav { display: none; }
  .foot-inner { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 620px) {
  .band { padding-block: var(--space-7); }
  .hero { padding-block: var(--space-7); }
  .display-l { font-size: var(--text-display-s); max-width: none; }
  .lede { font-size: var(--text-body); }
  .cta-row .btn { width: 100%; }
  .quote { padding: var(--space-4); }
}
