/* ═══════════════════════════════════════════════════════════════════════════
   pos-landing.css — the marketing lane.

   ── Why this is a FILE and not a <style> block ──────────────────────────────

   It began inline in public/index.html, which was correct while the landing
   page was the only marketing surface. It is not any more: routes/
   subsystemPages.js renders nine more of them (an index plus one per
   subsystem), and those pages are the SAME design language by definition,
   not by resemblance. Two copies of this vocabulary would drift the first
   time one of them was touched, and the divergence would be invisible until
   two pages were opened side by side.

   ── What it may and may not do ─────────────────────────────────────────────

   Everything here is --lp-* / .lp-*. It is deliberately NOT --r2-*
   (M-EasyDo's landing vocabulary, which this platform does not carry) and
   NOT --r3-* (pos-r3-tokens.css owns that namespace, and a second
   declaration site for a shared name is how a token stops being one).

   There is not one colour literal below. The accent is var(--accent), and
   var(--accent-text) wherever it is TEXT: #BE185D on white is 4.9:1 and the
   split token exists so body-sized accent text can be 7.6:1 instead.
   #BE185D itself lives in [data-platform="pos"] in the master and nowhere
   else, this file included.
   ═══════════════════════════════════════════════════════════════════════════ */
:root {
  /* rhythm */
  --lp-max: 1240px;
  --lp-gutter: clamp(20px, 5vw, 56px);
  --lp-section-y: clamp(64px, 8vw, 108px);
  --lp-measure: 62ch;

  /* type, one notch above the app's scale because a marketing headline and a
     page title are not the same job */
  --lp-display: clamp(2.5rem, 6vw, 4rem);
  --lp-headline: clamp(1.75rem, 3.4vw, 2.5rem);
  --lp-lede: clamp(1rem, 1.4vw, 1.1875rem);
  --lp-eyebrow: 11px;

  /* accent surfaces, derived from the one accent rather than restated */
  --lp-accent-wash: var(--accent-bg);
  --lp-accent-wash: color-mix(in srgb, var(--accent) 5%, transparent);
  --lp-accent-edge: var(--accent-glow);
  --lp-accent-edge: color-mix(in srgb, var(--accent) 30%, transparent);
  /* A separate, stronger mix for the one gradient on the page. 5% of the rose
     reads as a tint across a whole panel and as literally nothing across a
     radial falloff, which is a rule that costs a repaint and changes no pixel.
     Measured on #f8f9fa: 5% is indistinguishable, 9% is a warm cast you can
     see and still cannot name. */
  --lp-hero-wash: color-mix(in srgb, var(--accent) 13%, transparent);
  /* The grid is drawn in the ACCENT rather than in --border, which is the one
     deliberate difference from the reference. M-EasyDo draws its hairlines in
     the neutral border colour; here the same device carries the platform's
     rose, so the backdrop reads as this product's and not as a shared texture
     that happens to be under it. 22% keeps it below the weight of a real
     hairline, which matters: a grid as strong as the borders around it starts
     competing with the cards for the reader's sense of structure. */
  --lp-grid-line: color-mix(in srgb, var(--accent) 22%, transparent);
  --lp-glass: var(--surface);
  --lp-glass: color-mix(in srgb, var(--surface) 78%, transparent);
  --lp-stagger: 70ms;
}

/* Dark needs a bigger mix of the same hue to read as the same tint: 5% of a
   saturated rose is a perceptible warm cast on #f8f9fa and nothing at all on
   #0f172a. The ratio follows the master's own dark correction for
   --accent-light (0.08 -> 0.22), not a number picked by eye. */
[data-theme="dark"] {
  --lp-accent-wash: color-mix(in srgb, var(--accent) 13%, transparent);
  --lp-accent-edge: color-mix(in srgb, var(--accent) 42%, transparent);
  --lp-hero-wash: color-mix(in srgb, var(--accent) 20%, transparent);
  /* Same reasoning as the washes: a 22% mix of a mid-tone rose is a visible
     line on #f8f9fa and invisible on #0f172a. */
  --lp-grid-line: color-mix(in srgb, var(--accent) 40%, transparent);
  --lp-glass: color-mix(in srgb, var(--surface) 82%, transparent);
}

html { scroll-behavior: smooth; }
body {
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.6;
  background: var(--bg);
  color: var(--text);
  overflow-x: hidden;
}

/* ── rhythm ─────────────────────────────────────────────────────────────── */
.lp-wrap {
  width: 100%;
  max-width: var(--lp-max);
  margin-inline: auto;
  padding-inline: var(--lp-gutter);
}
.lp-section { padding-block: var(--lp-section-y); position: relative; }
.lp-section + .lp-section { border-top: 1px solid var(--border); }
section[id] { scroll-margin-top: 76px; }

/* ── type ───────────────────────────────────────────────────────────────── */
.lp-display {
  font-family: var(--font-display);
  font-size: var(--lp-display);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.035em;
  color: var(--text);
}
.lp-headline {
  font-family: var(--font-display);
  font-size: var(--lp-headline);
  font-weight: 700;
  line-height: 1.14;
  letter-spacing: -0.028em;
  color: var(--text);
}
.lp-subhead {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text);
}
.lp-lede { font-size: var(--lp-lede); color: var(--text-2); line-height: 1.62; max-width: var(--lp-measure); }
.lp-body { font-size: 15px; color: var(--muted); line-height: 1.7; max-width: var(--lp-measure); }
/* ONE headline on this page carries the accent, and it is the hero. An accent
   that appears on every heading marks none of them. */
.lp-accent { color: var(--accent-text); }
.lp-eyebrow {
  font-family: var(--font-mono);
  font-size: var(--lp-eyebrow);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.lp-head { display: flex; flex-direction: column; gap: 14px; margin-bottom: 44px; max-width: var(--lp-measure); }
.lp-head--center { align-items: center; text-align: center; margin-inline: auto; }
.lp-head--center .lp-lede { text-align: center; }

/* ── the grid backdrop ──────────────────────────────────────────────────── */
/* M-EasyDo's .r2-gridwash, restated here because this platform does not carry
   that file: a 64px hairline grid, masked so it fades out before it reaches
   the content it sits behind.

   STATIC, and that is the point of it. No beams, no parallax, nothing moving
   behind a headline. The device reads as considered precisely because it does
   not move, and an animated backdrop under display type is the most common way
   that reading is thrown away.

   Two layers, not one: this element draws the lines, and the accent gradient
   sits behind it on the parent's ::before. Keeping them apart means the tint
   can be tuned per placement without redrawing the grid, and the mask on each
   can differ. */
.lp-gridwash {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right, var(--lp-grid-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--lp-grid-line) 1px, transparent 1px);
  background-size: 64px 64px;
  opacity: 0.55;
  /* WIDER AND TALLER THAN THE REFERENCE'S MASK, because this hero is shorter
     than M-EasyDo's. The reference fades out at 78% of a 60% ellipse, which on
     a 700px hero lands at about 330px: the grid died just as the headline
     began, so the device read as a smudge along the top edge rather than as a
     field the hero sits on. Measured against the rendered page, not guessed. */
  -webkit-mask-image: radial-gradient(ellipse 95% 92% at 50% 0%, black 42%, transparent 95%);
  mask-image: radial-gradient(ellipse 95% 92% at 50% 0%, black 42%, transparent 95%);
}

/* ── icons ──────────────────────────────────────────────────────────────── */
/* One convention: 24-unit viewBox, no fill, currentColor stroke. No icon font
   and no CDN, so the page stays self-contained. */
.ico { width: 20px; height: 20px; flex-shrink: 0; display: block; }
/* display:block above out-specifies the UA's [hidden] rule, which is how a
   theme toggle ends up rendering the sun AND the moon at once. */
.ico[hidden] { display: none; }
.ico-16 { width: 16px; height: 16px; }
.ico-24 { width: 24px; height: 24px; }

/* NEUTRAL AT REST, ACCENT ON INTERACTION. Seven area tiles carrying an accent
   mark each is seven accent marks in one viewport, which is decoration.
   On hover and focus-within it becomes a state: "this is the one you are on".
   :focus-within is what keeps that off the pointer-only list. */
.lp-tile {
  width: 40px; height: 40px;
  border-radius: var(--r-sm);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-2);
  color: var(--text-2);
  border: 1px solid var(--border);
  flex-shrink: 0;
  transition: background var(--motion-base) var(--ease-out),
              color var(--motion-base) var(--ease-out),
              border-color var(--motion-base) var(--ease-out);
}
.lp-area:hover .lp-tile,
.lp-area:focus-within .lp-tile {
  background: var(--accent-bg);
  color: var(--accent-text);
  border-color: var(--lp-accent-edge);
}

/* ── nav ────────────────────────────────────────────────────────────────── */
.lp-nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 60;
  height: 60px;
  display: flex;
  align-items: center;
  gap: 18px;
  padding-inline: var(--lp-gutter);
  background: var(--lp-glass);
  backdrop-filter: blur(var(--r3-glass-blur));
  -webkit-backdrop-filter: blur(var(--r3-glass-blur));
  border-bottom: 1px solid var(--border);
}
/* A blurred bar over scrolling content is a material, and a material has to
   have a fallback: without backdrop-filter the bar would be 78% transparent
   over moving text. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .lp-nav { background: var(--surface); }
}
@media (prefers-reduced-transparency: reduce) {
  .lp-nav { background: var(--surface); backdrop-filter: none; -webkit-backdrop-filter: none; }
}
.lp-brand { display: inline-flex; align-items: center; gap: 9px; min-width: 0; color: var(--text); text-decoration: none; }
/* The app's own mark, to the pixel: r3-brand-mark in pos-r3-shell.css. The
   shell stylesheet is not loaded here (it lays out an app, not a document),
   so the one rule this page needs from it is restated rather than imported. */
.lp-mark {
  width: 26px; height: 26px;
  border-radius: 8px;
  background: var(--accent);
  color: var(--accent-contrast);
  display: grid; place-items: center;
  font-family: var(--font-display);
  font-size: 11px; font-weight: 700;
  flex-shrink: 0;
}
.lp-brand-text {
  font-family: var(--font); font-size: 15.5px; font-weight: 700; letter-spacing: -0.02em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lp-brand-plus { color: var(--muted); font-weight: 600; }
.lp-navlinks { display: flex; align-items: center; gap: 24px; }
.lp-navlinks a {
  font-size: 13.5px; font-weight: 500; color: var(--muted); text-decoration: none;
  transition: color var(--motion-fast) var(--ease-out);
}
.lp-navlinks a:hover { color: var(--text); }
.lp-navright { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.lp-navtoggle {
  display: none; align-items: center; justify-content: center;
  width: 38px; height: 38px; padding: 0;
  border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--surface); color: var(--text); cursor: pointer;
}
.lp-navtoggle:hover { background: var(--surface-2); }
.lp-iconbtn {
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--muted);
  cursor: pointer;
  transition: color var(--motion-fast) var(--ease-out), border-color var(--motion-fast) var(--ease-out);
}
.lp-iconbtn:hover { color: var(--text); border-color: var(--border-2); }

/* ── buttons (the design system's .btn, sized up for a marketing surface) ── */
.lp-cta { padding: 13px 24px; font-size: 15px; border-radius: var(--r-sm); }
.lp-cta { display: inline-flex; align-items: center; justify-content: center; gap: 2px; }
/* THE ARROW IS A PSEUDO-ELEMENT. A literal glyph in the label renders in Inter
   beside a page of 1.6px-stroke SVG, and cannot be animated. Masked from
   currentColor so it inherits the button's text colour in both themes, and
   aria-invisible by construction. */
.lp-cta::after {
  content: ''; width: 1em; height: 1em; margin-left: 0.15em; flex-shrink: 0;
  background: currentColor;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-size: contain; mask-size: contain;
  transition: transform var(--motion-base) var(--ease-out);
}
.lp-cta:hover::after, .lp-cta:focus-visible::after { transform: translateX(3px); }
/* A link that scrolls DOWN the page gets a down arrow. Keeping the animation
   and flipping nothing else would be a worse lie than no arrow at all. */
.lp-cta--down::after { -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 5v14M6 13l6 6 6-6'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 5v14M6 13l6 6 6-6'/%3E%3C/svg%3E"); }
.lp-cta--down:hover::after, .lp-cta--down:focus-visible::after { transform: translateY(3px); }
.lp-btnrow { display: flex; flex-wrap: wrap; gap: 12px; }

/* ── hero ───────────────────────────────────────────────────────────────── */
.lp-hero {
  position: relative;
  overflow: hidden;
  padding-top: calc(60px + clamp(48px, 6vw, 84px));
  padding-bottom: clamp(48px, 6vw, 84px);
}
.lp-hero::before {
  /* A single quiet wash behind the headline, anchored to the accent so it
     cannot drift from the brand. Not a mesh, not a blob, not a glow. */
  content: '';
  position: absolute; inset: -30% -10% auto -10%; height: 120%;
  background: radial-gradient(58% 46% at 50% 0%, var(--lp-hero-wash), transparent 72%);
  pointer-events: none;
}
.lp-hero-inner {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center;
  text-align: center; gap: 22px;
}
.lp-pill {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: var(--lp-eyebrow);
  letter-spacing: 0.06em;
  max-width: 100%;
}
.lp-pill-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); flex-shrink: 0; }
/* rem, NOT ch: `ch` is the width of "0" in the FIRST AVAILABLE font, so with
   display=swap it can be computed against the fallback and never recomputed
   once Outfit arrives, which moves the hero on load. */
.lp-hero h1 { max-width: 20em; }
.lp-hero .lp-lede { max-width: 34rem; text-align: center; }

/* ── the two propositions ───────────────────────────────────────────────── */
/* THIS BAND HAS NO NUMBERS IN IT, AND THE ABSENCE IS THE DECISION.

   It shipped as four counts (`7 Areas · 26 Screens · 70 Prepared questions ·
   4 POS connectors`), then as two claims with the counts underneath as
   evidence. Both versions asked the reader to do arithmetic about a product
   they have not opened: nobody arriving here knows whether 26 screens is a lot
   or whether 70 questions is generous, so the figures were decoration wearing
   a data label. What each proposition claims is the whole content now, and the
   sections below are where the specifics are earned.

   With the figures gone the type carries the band alone, so it is set one
   step up from body copy rather than at the size it was under a 30px numeral. */
.lp-figures { background: var(--surface); border-block: 1px solid var(--border); padding-block: clamp(34px, 4.4vw, 52px); }
.lp-props {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(28px, 4vw, 56px);
}
/* The divider is a border on the second column rather than a rule element:
   one line that cannot fall out of step with the gap it sits in. */
.lp-prop + .lp-prop { border-left: 1px solid var(--border); padding-left: clamp(28px, 4vw, 56px); }
.lp-prop-title {
  font-family: var(--font-display);
  font-size: clamp(1.1875rem, 1.8vw, 1.5rem); font-weight: 700;
  letter-spacing: -0.024em;
  color: var(--text);
}
.lp-prop-line { margin-top: 12px; font-size: 15px; color: var(--text-2); line-height: 1.65; max-width: 34rem; }

/* ── the product shots ──────────────────────────────────────────────────── */
.lp-shot {
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--surface);
  box-shadow: var(--shadow-lg);
}
.lp-shot-bar {
  display: flex; align-items: center; gap: 7px;
  padding: 11px 15px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}
.lp-shot-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--border-2); flex-shrink: 0; }
.lp-shot-path { margin-left: 8px; font-family: var(--font-mono); font-size: 11px; color: var(--muted); }
.lp-shot img, .lp-phone img { display: block; width: 100%; height: auto; }
.lp-caption { margin-top: 12px; font-size: 12.5px; color: var(--muted); text-align: center; }

/* THEME-MATCHED SCREENSHOTS, AND IT IS NOT A NICETY.
   Every shot on this page is a real capture of this product, and this product
   has both themes. A light capture on the dark page is a 1400px white panel in
   the middle of a #0f172a document: it does not read as a screenshot, it reads
   as an image that failed to load its own styling.

   NOT <picture> with a media query. This ecosystem's theme is a TOGGLE writing
   data-theme, deliberately, so prefers-color-scheme is the wrong question and
   would keep showing the light shot to someone who just pressed the moon.

   display:none rather than visibility or opacity, so exactly one of the two is
   in the accessibility tree and a screen reader is not read the same alt text
   twice. Both carry the same alt for that reason. */
/* SCOPED TO THE SAME PARENTS AS THE RULE THEY HAVE TO BEAT, and that is the
   whole reason these selectors are not the bare classes they look like they
   should be. `.lp-shot img` above is (0,1,1); a bare `.lp-img-dark` is (0,1,0)
   and loses on specificity no matter where it sits in the file, so BOTH
   screenshots rendered, one under the other, in both themes. Measured, not
   guessed: getComputedStyle(dark).display was 'block' on a light page. */
.lp-shot .lp-img-dark,  .lp-phone .lp-img-dark  { display: none; }
[data-theme="dark"] .lp-shot .lp-img-light,
[data-theme="dark"] .lp-phone .lp-img-light { display: none; }
[data-theme="dark"] .lp-shot .lp-img-dark,
[data-theme="dark"] .lp-phone .lp-img-dark  { display: block; }

/* The terminal is a 1400px-wide desktop screen. Squeezed into a 350px phone it
   is a grey smudge, so below the split it keeps a readable width and pans
   inside its own frame instead. The page body never scrolls sideways. */
@media (max-width: 760px) {
  .lp-shot-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .lp-shot-scroll img { width: 720px; max-width: none; }
}

/* ── the eight subsystems ───────────────────────────────────────────────── */
/* A six-track grid, so a wide cell is genuinely twice a narrow one rather
   than a narrow one with padding. Eight items, eight cells, no filler tile:

     4+2 / 2+4 / 2+2+2 / 6

   The two wide cells swap sides between row one and row two. Stacked on the
   same side they read as a column of big cards beside a column of small ones,
   which is a two-column layout with extra steps; alternated, the eye crosses
   the grid and the rows stop looking like repeats of each other.

   Placement is DOM order, not explicit column starts. Auto-placement fills
   a 4 then a 2, then a 2 then a 4, and so on, so re-ordering the cards
   re-flows the grid instead of leaving a hole where a hard-coded start was. */
.lp-areas { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 16px; }
.lp-area {
  grid-column: span 2;
  display: flex; flex-direction: column; gap: 11px;
  padding: clamp(20px, 2.4vw, 28px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  text-decoration: none;
  transition: border-color var(--motion-base) var(--ease-out),
              box-shadow var(--motion-base) var(--ease-out);
}
.lp-area:hover, .lp-area:focus-within { border-color: var(--lp-accent-edge); box-shadow: var(--shadow-lg); }
/* THE TWO WIDE CELLS ARE ALSO THE TWO DARKER ONES, and that is the grid's
   rhythm rather than decoration. Seven identical white cards read as a table
   with rounded corners: nothing in the composition says which of the seven is
   the product's centre of gravity, and Sell and Stock are (the other five
   exist to keep the till stocked, priced and reconciled). A surface step does
   that without spending the accent, which on this page is already carrying the
   hero word, the ask panel and the closing box. */
.lp-area--wide { grid-column: span 4; background: var(--surface-2); }
.lp-area--full { grid-column: span 6; background: var(--surface-2); }
.lp-area-title { font-family: var(--font-display); font-size: 17px; font-weight: 700; letter-spacing: -0.02em; color: var(--text); }
.lp-area-desc { font-size: 13.5px; color: var(--muted); line-height: 1.6; }
.lp-area-list { list-style: none; display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; }
.lp-area-list .tag { font-size: 11px; padding: 3px 9px; }
/* The tile and the pills are defined against --surface / --bg-soft, so on the
   stepped-back card they would sit within a percent or two of their own
   background and stop being objects. They step the other way instead. */
.lp-area--wide .lp-tile, .lp-area--full .lp-tile,
.lp-area--wide .lp-area-list .tag,
.lp-area--full .lp-area-list .tag { background: var(--surface); }
/* The wide cells carry the same copy across twice the width, so they put the
   description and the screen list side by side. The extra width is used
   rather than merely occupied. */
@media (min-width: 861px) {
  .lp-area--wide { display: grid; grid-template-columns: 1fr 1fr; column-gap: 26px; row-gap: 11px; grid-template-rows: auto auto 1fr; }
  .lp-area--wide > .lp-tile, .lp-area--wide > .lp-area-title { grid-column: 1 / -1; }
  .lp-area--wide .lp-area-desc { grid-column: 1; }
  .lp-area--wide .lp-area-list { grid-column: 2; align-content: start; }

  /* The full-width cell turns the other way: the tile, name and description
     stack down the left and the screen list takes the whole right side,
     vertically centred against them. Given the same treatment as a wide cell
     it would be a wide cell with 300px of empty space after the tags, which
     is how a full-bleed row usually goes wrong. */
  .lp-area--full {
    display: grid;
    grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
    /* THE ROWS ARE DECLARED, and they have to be. `grid-row: 1 / -1` on the
       tag list below resolves -1 against the EXPLICIT grid, so with no
       grid-template-rows the explicit grid has one line, -1 IS line 1, and the
       span collapses to row one. The tags then sat at the top of the card with
       the description alone underneath, which is the bug this looked like a
       fix for. Three rows: tile, name, description. */
    grid-template-rows: auto auto auto;
    column-gap: clamp(28px, 4vw, 56px);
    row-gap: 11px;
    align-items: start;
  }
  .lp-area--full > .lp-tile,
  .lp-area--full > .lp-area-title,
  .lp-area--full > .lp-area-desc { grid-column: 1; }
  /* align-SELF, not align-content. The list spans all three rows, but it is a
     flex container, so align-content governs its own children and does nothing
     about where the box itself sits in the area it spans. With the parent at
     `align-items: start` the tags pinned to the top of a card whose left
     column is three rows tall, leaving the bottom right of a full-width row
     empty. This is the property that actually centres it. */
  .lp-area--full > .lp-area-list { grid-column: 2; grid-row: 1 / -1; align-self: center; }
}

/* ── the split (copy beside the phone) ──────────────────────────────────── */
.lp-split { display: grid; grid-template-columns: 1.05fr 0.95fr; gap: clamp(32px, 5vw, 72px); align-items: center; }
.lp-checks { list-style: none; display: flex; flex-direction: column; gap: 11px; margin: 22px 0 26px; padding: 0; }
.lp-checks li { display: flex; gap: 10px; font-size: 14.5px; color: var(--text-2); line-height: 1.55; }
.lp-checks .ico { color: var(--muted); margin-top: 3px; }
.lp-phone {
  justify-self: center;
  max-width: 300px; width: 100%;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--surface);
  box-shadow: var(--shadow-lg);
}
.lp-phone img { display: block; width: 100%; height: auto; }

/* ── the ask banner ─────────────────────────────────────────────────────── */
.lp-ask {
  display: grid; grid-template-columns: 1fr 1fr; gap: clamp(28px, 4vw, 56px); align-items: center;
  padding: clamp(28px, 4vw, 52px);
  border: 1px solid var(--lp-accent-edge);
  border-radius: var(--r-lg);
  background: var(--lp-accent-wash);
}
.lp-questions { list-style: none; display: flex; flex-direction: column; gap: 10px; margin: 0; padding: 0; }
/* No icon on the row, and its absence is the decision. Four identical glyphs
   down the left of four list items is the same shape of tell as a coloured dot
   before every nav link: it repeats without distinguishing, and the reader
   already knows a question mark when they see one. */
.lp-question {
  display: block;
  padding: 13px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  font-size: 14px; color: var(--text);
  line-height: 1.5;
}
.lp-note { margin-top: 18px; font-size: 13px; color: var(--muted); line-height: 1.6; }

/* ── the tax states ─────────────────────────────────────────────────────── */
.lp-states { display: flex; flex-direction: column; gap: 0; border: 1px solid var(--border); border-radius: var(--r); overflow: hidden; background: var(--surface); }
.lp-state { display: grid; grid-template-columns: 108px 1fr; gap: 18px; padding: 18px 20px; align-items: start; }
.lp-state + .lp-state { border-top: 1px solid var(--border); }
.lp-state-key { display: block; font-family: var(--font-mono); font-size: 12px; font-weight: 600; color: var(--accent-text); letter-spacing: 0.04em; padding-top: 2px; }
/* display:block is load-bearing, not tidiness. As inline boxes these two ran
   together into one paragraph, so the title read as the first clause of its
   own description and margin-top did nothing. */
.lp-state-title { display: block; font-size: 14.5px; font-weight: 600; color: var(--text); }
.lp-state-desc { display: block; margin-top: 4px; font-size: 13px; color: var(--muted); line-height: 1.6; }

/* ── how it works ───────────────────────────────────────────────────────── */
.lp-steps { margin-top: 8px; margin-bottom: 0; }
.lp-steps .step { padding-inline: 14px; }
/* The accent, spent once more where it earns it: the numbered rail is the
   only thing on this page a reader has to follow in order. */
.lp-steps .step-dot { border-color: var(--lp-accent-edge); color: var(--accent-text); }
.lp-step-desc { margin-top: 6px; font-size: 12.5px; color: var(--muted); line-height: 1.55; text-align: center; }
@media (max-width: 720px) {
  .lp-steps { flex-wrap: wrap; overflow-x: visible; row-gap: 28px; }
  .lp-steps .step { flex: 1 1 42%; min-width: 132px; }
  .lp-steps .step:not(:last-child)::after { display: none; }
}

/* ── closing ────────────────────────────────────────────────────────────── */
.lp-ctabox {
  position: relative; overflow: hidden;
  border: 1px solid var(--lp-accent-edge);
  border-radius: var(--r-xl);
  background: var(--lp-accent-wash);
  padding: clamp(40px, 6vw, 72px) clamp(22px, 4vw, 52px);
  text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 18px;
  max-width: 860px; margin-inline: auto;
}
/* The gridwash inside the box is absolutely positioned, and an absolutely
   positioned element paints ABOVE non-positioned in-flow siblings. Without
   this the grid would be drawn over the headline rather than behind it. */
.lp-ctabox > * { position: relative; z-index: 1; }
.lp-ctabox > .lp-gridwash { z-index: 0; }
.lp-ctabox .lp-lede { text-align: center; max-width: 32rem; }
.lp-ctanote { font-size: 13px; color: var(--muted); max-width: 34rem; }
.lp-ctanote strong { color: var(--text-2); font-weight: 600; }

/* ── footer ─────────────────────────────────────────────────────────────── */
.lp-footer {
  border-top: 1px solid var(--border);
  padding: 28px var(--lp-gutter);
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 16px;
}
.lp-footer-copy { font-size: 13px; color: var(--muted); }
.lp-footer-links { display: flex; gap: 22px; }
.lp-footer-links a { font-size: 13px; color: var(--muted); text-decoration: none; transition: color var(--motion-fast) var(--ease-out); }
.lp-footer-links a:hover { color: var(--text); }

/* ── staggered reveal ───────────────────────────────────────────────────── */
/* Order carried by position rather than by an inline custom property, so no
   surface here declares a token it does not own. */
[data-reveal="on"] .lp-stagger > .reveal:nth-child(1) { transition-delay: 0ms; }
[data-reveal="on"] .lp-stagger > .reveal:nth-child(2) { transition-delay: calc(1 * var(--lp-stagger)); }
[data-reveal="on"] .lp-stagger > .reveal:nth-child(3) { transition-delay: calc(2 * var(--lp-stagger)); }
[data-reveal="on"] .lp-stagger > .reveal:nth-child(4) { transition-delay: calc(3 * var(--lp-stagger)); }
[data-reveal="on"] .lp-stagger > .reveal:nth-child(5) { transition-delay: calc(4 * var(--lp-stagger)); }
[data-reveal="on"] .lp-stagger > .reveal:nth-child(6) { transition-delay: calc(5 * var(--lp-stagger)); }
[data-reveal="on"] .lp-stagger > .reveal:nth-child(7) { transition-delay: calc(6 * var(--lp-stagger)); }
[data-reveal="on"] .lp-stagger > .reveal:nth-child(8) { transition-delay: calc(7 * var(--lp-stagger)); }

/* ── responsive ─────────────────────────────────────────────────────────── */
@media (max-width: 980px) {
  /* NOT display:none. Four in-page anchors deleted on every tablet and phone
     is removal, not collapse. They live behind a disclosure that is
     keyboard-operable and Escape-dismissable, matching the contract the rest
     of this ecosystem's menus already use. */
  /* Only once JS has confirmed it can operate it: without this the no-JS
     render shows a hamburger that does nothing AND keeps the links hidden,
     which is strictly worse than the bug it replaces. */
  [data-nav="on"] .lp-navtoggle { display: inline-flex; }
  :root:not([data-nav="on"]) .lp-navlinks {
    display: flex; flex-direction: row; position: static;
    background: none; border: 0; box-shadow: none; padding: 0; gap: 14px; flex-wrap: wrap;
  }
  .lp-navlinks {
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    padding: 6px;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow-lg);
  }
  .lp-navlinks:not(.is-open) { display: none; }
  .lp-navlinks a { padding: 12px 14px; border-radius: var(--r-sm); font-size: 15px; }
  .lp-navlinks a:hover, .lp-navlinks a:focus-visible { background: var(--surface-2); }
}
@media (max-width: 860px) {
  /* The vertical divider becomes a horizontal one. It cannot simply be
     dropped: the two propositions are separate claims, and stacked with no
     rule between them the second reads as more body copy under the first. */
  .lp-props { grid-template-columns: 1fr; gap: 26px; }
  .lp-prop + .lp-prop { border-left: 0; padding-left: 0; border-top: 1px solid var(--border); padding-top: 26px; }
  .lp-areas { grid-template-columns: 1fr; }
  .lp-area, .lp-area--wide, .lp-area--full { grid-column: auto; }
  .lp-split { grid-template-columns: 1fr; }
  .lp-ask { grid-template-columns: 1fr; }
  .lp-phone { max-width: 320px; }
}
@media (max-width: 640px) {
  .lp-state { grid-template-columns: 1fr; gap: 6px; }
  .lp-footer { justify-content: center; text-align: center; }
  .lp-cta { padding: 12px 20px; font-size: 14px; }
}
@media (max-width: 560px) {
  /* The wordmark is dropped, not truncated: at this width it ellipsised to
     "M…", which reads as a rendering bug. The mark stays, the link keeps the
     full name as its accessible name, and the footer still prints it. */
  .lp-nav .lp-brand-text { display: none; }
  /* Two CTAs of different widths stacked centre-aligned read as ragged. */
  .lp-hero .lp-btnrow { flex-direction: column; align-items: stretch; width: 100%; max-width: 320px; }
  .lp-hero .lp-btnrow .btn { justify-content: center; }
}

/* ═══ REDUCED MOTION ════════════════════════════════════════════════════════
   §41 of the master already flattens every duration and already collapses
   .reveal to its FINAL state, so nothing here can leave content invisible.
   What §41 cannot know about is what this file introduces, so each addition
   is named rather than swept up by a blanket rule. ═══════════════════════ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  /* A stagger delay on a transition that no longer runs only postpones the
     jump to the end state. */
  [data-reveal="on"] .lp-stagger > .reveal { transition-delay: 0ms; }
  /* Hover nudges: nothing is communicated by them that the hover colour and
     the pointer do not already say. */
  .lp-tile { transition: none; }
  .lp-cta:hover::after, .lp-cta:focus-visible::after { transform: none; }
  .lp-cta--down:hover::after, .lp-cta--down:focus-visible::after { transform: none; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   THE SUBSYSTEM PAGES
   ───────────────────────────────────────────────────────────────────────────
   Everything above is shared with public/index.html. What follows is used only
   by routes/subsystemPages.js: the per-system hero, the screen grid, and the
   row of siblings at the foot of each page.

   ONE ACCENT ACROSS ALL NINE PAGES, and that is a decision this platform has
   already taken once. pos-r3-tokens.css records why M-EasyDo's six derived
   business-area hues were not ported: giving each area its own colour IS
   importing a colour theme, and it leaves the brand accent marking nothing
   because it is everywhere. The reference implementation these pages follow
   gives every subsystem its own RGB triple. This one does not. The subsystems
   are told apart by name, position and icon.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── the breadcrumb ─────────────────────────────────────────────────────── */
/* A subsystem page is reached from somewhere, and unlike the landing page it
   is not the top of anything. The crumb is the way back, and it is a real
   link rather than a label. */
.lp-crumb {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 13px; color: var(--muted);
}
.lp-crumb a { color: var(--muted); text-decoration: none; transition: color var(--motion-fast) var(--ease-out); }
.lp-crumb a:hover { color: var(--text); }
.lp-crumb-sep { color: var(--border-2); }
.lp-crumb-here { color: var(--text-2); font-weight: 600; }

/* ── the emblem ─────────────────────────────────────────────────────────── */
/* Bigger than .lp-tile and, unlike it, accented at REST. On the landing page
   an accent tile on each of eight cards marks nothing; here there is exactly
   one on the page and it is the subject of it. */
.lp-emblem {
  width: 62px; height: 62px;
  border-radius: var(--r);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent-bg);
  color: var(--accent-text);
  border: 1px solid var(--lp-accent-edge);
}

/* ── the screen grid ────────────────────────────────────────────────────── */
/* auto-fit, not a fixed column count. These grids hold anything from one
   screen (M-EasyWorkforce) to eight (M-EasyStock), and a fixed three columns
   would leave two empty cells on the first and a ragged last row on the
   second. The track floor is what stops a lone card stretching to full width
   and reading as a banner. */
.lp-features {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 16px;
}
/* One screen is a legitimate subsystem, and it must not look like a mistake.
   Capped so a single card sits at the width it would have had among others. */
.lp-features--one { grid-template-columns: minmax(0, 380px); }
.lp-feature {
  display: flex; flex-direction: column; gap: 10px;
  padding: clamp(20px, 2.4vw, 26px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  transition: border-color var(--motion-base) var(--ease-out),
              box-shadow var(--motion-base) var(--ease-out);
}
.lp-feature:hover { border-color: var(--lp-accent-edge); box-shadow: var(--shadow-lg); }
.lp-feature-name { font-family: var(--font-display); font-size: 16px; font-weight: 700; letter-spacing: -0.02em; color: var(--text); }
.lp-feature-desc { font-size: 13.5px; color: var(--muted); line-height: 1.62; }
/* The path is what the screen is CALLED in the product, printed so the page
   and the shell can be checked against each other by eye. Mono, because it is
   a URL and not prose. */
.lp-feature-path { margin-top: auto; padding-top: 12px; font-family: var(--font-mono); font-size: 11px; color: var(--muted); border-top: 1px solid var(--border); }

/* ── the siblings row ───────────────────────────────────────────────────── */
.lp-siblings { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 12px; }
.lp-sibling {
  display: flex; align-items: center; gap: 12px;
  padding: 15px 17px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  text-decoration: none;
  transition: border-color var(--motion-base) var(--ease-out), background var(--motion-base) var(--ease-out);
}
.lp-sibling:hover { border-color: var(--lp-accent-edge); background: var(--surface-2); }
.lp-sibling .lp-tile { width: 34px; height: 34px; border-radius: var(--r-sm); }
.lp-sibling:hover .lp-tile { background: var(--accent-bg); color: var(--accent-text); border-color: var(--lp-accent-edge); }
.lp-sibling-name { font-family: var(--font-display); font-size: 14px; font-weight: 700; letter-spacing: -0.015em; color: var(--text); }

/* ── the subsystem hero ─────────────────────────────────────────────────── */
/* Left-aligned, where the landing page's is centred. The landing hero is a
   manifesto and the centre suits it; this one is the top of a document about
   one thing, and it reads as a heading rather than a poster. */
.lp-hero--system { padding-bottom: clamp(40px, 5vw, 64px); }
.lp-hero--system .lp-hero-inner { align-items: flex-start; text-align: left; }
.lp-hero--system h1 { max-width: 16em; }
.lp-hero--system .lp-lede { text-align: left; max-width: 40rem; }
@media (max-width: 560px) {
  .lp-hero--system .lp-btnrow { flex-direction: column; align-items: stretch; width: 100%; max-width: 320px; }
  .lp-hero--system .lp-btnrow .btn { justify-content: center; }
}

/* ── the subsystem index grid ───────────────────────────────────────────── */
/* NOT .lp-areas, and the difference is not cosmetic. That grid is six fixed
   tracks with every card spanning two, which is what makes the landing page's
   4+2 / 2+4 / 2+2+2 / 6 rhythm possible. Reusing it here with an auto-fit
   column list produced THREE tracks at 1240px (4 x 300 + 3 x 16 overflows,
   3 x 300 + 2 x 16 does not), and a card spanning two of three tracks is one
   card per row with a third of every row empty. Measured, not guessed.

   The index wants none of that rhythm. Eight equal cards, as many per row as
   fit, so the span is reset rather than inherited. */
.lp-modgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 16px;
}
.lp-modgrid > .lp-area { grid-column: auto; }

/* The index has no section heading between its hero and its cards, so it gets
   the hero's bottom padding AND a full section's top padding with nothing in
   between. Measured at ~195px of empty band at 1440. Halved: the cards are
   what the page is for. */
.lp-section--tight { padding-top: clamp(24px, 3vw, 44px); }

/* ═══════════════════════════════════════════════════════════════════════════
   §L — THE LIVELY LAYER
   ───────────────────────────────────────────────────────────────────────────
   Everything above was written in M-EasyDo's R2 idiom, which spends the accent
   ONCE per screen on purpose. Read end to end that page is calm; read as a
   first impression it is grey, and a marketing surface is only ever read as a
   first impression.

   M-EasyTools is the reference for the correction, and its devices are all
   token-based rather than hand-mixed. Taken here, in order of how much each
   changes: a layered hero glow instead of one flat wash, an accent-filled
   badge with a live dot, accent eyebrows instead of muted ones, an accent
   gradient across the top of every card, tiles that carry the accent AT REST,
   a lift on hover, accent-banded sections, and a stepper with real nodes.

   WHAT IS NOT TAKEN. Tools is dark-only and can push saturation harder than a
   page that also has to work on #f8f9fa. Every value below was set by looking
   at BOTH themes; where one number could not serve both, the dark block
   overrides it rather than the light one being pushed until it shows.

   Still one hue, and still not a colour literal anywhere in it.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* Tokens because three surfaces use them: the hero, the closing box and the
     eight subsystem heroes. */
  --lp-glow:      color-mix(in srgb, var(--accent) 18%, transparent);
  --lp-glow-2:    color-mix(in srgb, var(--accent)  7%, transparent);
  --lp-card-wash: color-mix(in srgb, var(--accent)  7%, transparent);
}
[data-theme="dark"] {
  --lp-glow:      color-mix(in srgb, var(--accent) 34%, transparent);
  --lp-glow-2:    color-mix(in srgb, var(--accent) 15%, transparent);
  --lp-card-wash: color-mix(in srgb, var(--accent) 14%, transparent);
}

/* ── L1. the hero glow ──────────────────────────────────────────────────── */
/* TWO radials, not one. A single centred wash fades evenly in every direction
   and reads as a flat tint; a second, smaller, off-axis one gives the field a
   direction and therefore a shape. Both are the same hue, so this is depth
   rather than a second accent. */
.lp-hero::before {
  background:
    radial-gradient(ellipse 62% 52% at 50% -4%, var(--lp-glow), transparent 70%),
    radial-gradient(ellipse 42% 40% at 88% 88%, var(--lp-glow-2), transparent 66%);
}

/* ── L2. the badge ──────────────────────────────────────────────────────── */
/* It was a neutral pill with grey text, which is a label. Filled and accented
   it becomes the first thing on the page that says whose product this is. */
.lp-pill {
  background: var(--accent-bg);
  border-color: var(--lp-accent-edge);
  color: var(--accent-text);
  font-weight: 600;
}
/* The dot is the only looping animation on the page, it is 6px across, and it
   sits on a badge announcing a live product. That is a STATE, which is the one
   thing a perpetual animation is allowed to be. */
@media (prefers-reduced-motion: no-preference) {
  .lp-pill-dot { animation: lp-pulse 2.4s ease-in-out infinite; }
}
@keyframes lp-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }

/* ── L3. type with more presence ────────────────────────────────────────── */
:root {
  --lp-display:  clamp(2.75rem, 6.6vw, 4.5rem);
  --lp-headline: clamp(1.875rem, 3.6vw, 2.75rem);
}
.lp-display  { font-weight: 800; letter-spacing: -0.04em; }
.lp-headline { font-weight: 800; }

/* ── L4. the brand mark ─────────────────────────────────────────────────── */
/* Flat accent to a gradient between the accent and its own darker step. Two
   tokens, one hue, and the mark stops reading as a placeholder square. */
.lp-mark { background: linear-gradient(135deg, var(--accent), var(--accent-2)); }

/* ── L5. eyebrows carry the accent ──────────────────────────────────────── */
/* --accent-text, never --accent: the raw rose is 4.9:1 on white and this is
   11px type. The split token exists for exactly this, and measures 7.6:1. */
.lp-eyebrow { color: var(--accent-text); letter-spacing: 0.18em; }

/* ── L6. cards that are not white rectangles ────────────────────────────── */
/* The wash runs from the top-left corner and is gone by 55%, so a card gets a
   lit edge rather than an all-over tint. --surface stays underneath as the
   base, which is what leaves the text contrast where it was. */
.lp-area, .lp-feature, .lp-sibling, .lp-question {
  background: linear-gradient(150deg, var(--lp-card-wash), transparent 55%), var(--surface);
}
/* The stepped-back cells now step back from a LIT card rather than a white
   one, or the wash would make them read as lighter than their neighbours. */
.lp-area--wide, .lp-area--full {
  background: linear-gradient(150deg, var(--lp-card-wash), transparent 55%), var(--surface-2);
}

/* THE TILES CARRY THE ACCENT AT REST, reversing the rule above them.
   That rule held the colour back to hover, arguing eight accent marks in one
   viewport is decoration. True of a page carrying accent elsewhere, false of
   this one: with the tiles neutral there was nothing coloured at all between
   the hero and the footer. Hover now moves the whole CARD, which is a stronger
   signal than recolouring a 40px square ever was. */
.lp-tile { background: var(--accent-bg); color: var(--accent-text); border-color: var(--lp-accent-edge); }
.lp-area--wide .lp-tile, .lp-area--full .lp-tile { background: var(--accent-bg); }

/* A lift, a ring and a shadow. transform and box-shadow only, both composited,
   and both dropped under reduced motion at the foot of this section. */
.lp-area, .lp-feature, .lp-sibling {
  transition: transform var(--motion-base) var(--ease-out),
              border-color var(--motion-base) var(--ease-out),
              box-shadow var(--motion-base) var(--ease-out);
}
.lp-area:hover, .lp-area:focus-within,
.lp-feature:hover, .lp-feature:focus-within,
.lp-sibling:hover, .lp-sibling:focus-within {
  transform: translateY(-3px);
  border-color: var(--lp-accent-edge);
  box-shadow: var(--shadow-lg), 0 0 0 1px var(--lp-accent-edge);
}

/* ── L7. banded sections ────────────────────────────────────────────────── */
/* A soft accent band top to bottom, so the page has warm stretches and cool
   ones instead of one flat ground for twelve thousand pixels. Applied to two
   sections only, the two longest runs of unbroken --bg. */
.lp-section--band {
  background: linear-gradient(180deg, transparent, var(--lp-card-wash) 52%, transparent);
}

/* ── L8. the stepper ────────────────────────────────────────────────────── */
/* The master 32px dot is a form-wizard control. On a marketing page the four
   steps ARE the argument, so the node is 56px, filled with the accent tint and
   carrying its number at display weight. Tools' device, and it reads at a
   glance where a 13px numeral inside a hairline ring does not. */
.lp-steps .step-dot {
  width: 56px; height: 56px;
  background: var(--accent-bg);
  border: 1px solid var(--lp-accent-edge);
  color: var(--accent-text);
  font-family: var(--font-display);
  font-size: 20px; font-weight: 800;
}
/* The rail between them, drawn from the accent and faded at both ends so it
   does not collide with the nodes it joins. Re-aimed at the taller node: the
   master centres it on a 32px dot, and left alone it would cross them. */
.lp-steps .step:not(:last-child)::after {
  top: 28px;
  left: calc(50% + 34px);
  right: calc(-50% + 34px);
  background: linear-gradient(90deg, transparent, var(--lp-accent-edge), transparent);
}
.lp-steps .step-label { margin-top: 14px; font-size: 14px; font-weight: 700; color: var(--text); }

/* ── L9. the emblem on a subsystem page ─────────────────────────────────── */
.lp-emblem {
  background: linear-gradient(150deg, var(--accent-bg), transparent), var(--surface);
  box-shadow: 0 10px 30px var(--lp-glow-2);
}

/* ── L10. the closing box ───────────────────────────────────────────────── */
/* It already carried the wash and the grid. What it did not have was the glow,
   which is what makes it read as the END of the page rather than one more
   panel on it. Behind the content: .lp-ctabox > * is already z-index 1. */
.lp-ctabox::after {
  content: '';
  position: absolute; left: 50%; top: 50%;
  width: min(620px, 90%); height: 70%;
  transform: translate(-50%, -50%);
  background: radial-gradient(ellipse at center, var(--lp-glow-2), transparent 68%);
  pointer-events: none;
  z-index: 0;
}

/* ═══ REDUCED MOTION ════════════════════════════════════════════════════════
   §41 flattens durations globally. What it cannot know about is what THIS
   section introduced, so each addition is named rather than assumed covered. */
@media (prefers-reduced-motion: reduce) {
  .lp-pill-dot { animation: none; }
  .lp-area:hover, .lp-area:focus-within,
  .lp-feature:hover, .lp-feature:focus-within,
  .lp-sibling:hover, .lp-sibling:focus-within { transform: none; }
}

/* ── the public demo panel ──────────────────────────────────────────────────
   Tokens only, and only ones this stylesheet already uses: --surface,
   --border, --text, --text-2, --muted, --radius-lg, --font-mono. No
   fallbacks: a fallback is one fixed value and this page has two themes,
   which is the warning test/css-token-test.js exists to raise. */
.lp-demo { max-width: 780px; margin-inline: auto; border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface); padding: 22px; }
.lp-demo-table { width: 100%; border-collapse: collapse; font-size: 14px; color: var(--text); }
.lp-demo-table th { text-align: left; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); padding: 0 10px 10px; font-weight: 600; }
.lp-demo-table td { padding: 11px 10px; border-top: 1px solid var(--border); vertical-align: top; }
.lp-demo-table code { font-family: var(--font-mono); font-size: 13px; }
.lp-demo-role { font-weight: 600; white-space: nowrap; }
.lp-demo-sees { color: var(--text-2); }
.lp-demo-pw { text-align: center; margin: 18px 0 0; font-size: 14px; color: var(--text); }
.lp-demo-pw code { font-family: var(--font-mono); font-size: 14px; }
.lp-demo-note { text-align: center; margin: 14px 0 0; font-size: 13px; color: var(--muted); line-height: 1.6; }
/* Three stacked rows rather than a sideways scroll: a credential you have to
   scroll to read is a credential nobody uses. */
@media (max-width: 640px) {
  .lp-demo-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .lp-demo-table tr { display: block; border-top: 1px solid var(--border); padding: 12px 0; }
  .lp-demo-table td { display: block; border: 0; padding: 2px 0; }
}
