/* ==========================================================================
   CompareIt — landing page layer
   Loaded by welcome.html only, after tokens.css and base.css.

   This page is deliberately NOT a Blazor route. It is served at "/" by a
   staticwebapp.config.json rewrite so it paints on the first byte instead of
   waiting on the WASM runtime, and so a crawler sees copy instead of the
   loading shell. The app itself lives at /feed.

   Consequence: Blazor's CSS isolation bundle (CompareIt.Client.styles.css) is
   scoped with generated b-* attributes and cannot be reached from a plain HTML
   document. So three pieces of chrome — the app bar, the wordmark and the
   theme toggle — are re-implemented here. They are re-implemented from the
   SAME tokens, never from raw hex, so the two copies cannot drift on any
   VALUE; only the selectors differ. If §7.1 / §7.2b of design.md change, this
   file changes with them.

   Everything below obeys design.md:
   §3  a hue is a meaning — violet action, teal reference, lime subject,
       amber award, coral like. Nothing here is coloured for decoration.
   §3  the app bar is ink in BOTH themes, so anything drawn on it reads from
       the RAW ramp (--n-500, --sp-teal, #fff), never the semantic layer.
   §4  the display face is for the wordmark and the page title only. Section
       headings are the UI face at 700.
   §4  every number, unit and eyebrow label is mono.
   §6  one layout from 320px to 2560px.
   §9  AA contrast, visible focus, 44px targets, reduced motion honoured.
   ========================================================================== */

/* So an in-page anchor (#capture, #compare, #how) never lands a heading under
   the sticky bar + rule. Unscoped on purpose — this file is only ever loaded
   by welcome.html. */
html { scroll-padding-top: 72px; }

/* Landing-only measures. Scoped to this file on purpose: tokens.css is the
   app's contract and a marketing page should not widen it. The app's
   --shell-max (1600) is a grid ceiling; prose needs a much tighter one. */
.lp {
  --lp-max: 1120px;    /* section content ceiling */
  --lp-prose: 62ch;    /* readable measure for any run of body copy */
}

/* ------------------------------------------------------------------ bar --
   design.md §7.1 — ink in both themes, sticky, wordmark hard left. The right
   slot carries the theme toggle and the CTA instead of the safety toggle:
   SFW/NSFW slices a feed, and there is no feed on this page. */
.lp-bar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--n-050);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  min-height: 56px;
  padding-top: env(safe-area-inset-top, 0px);
  padding-inline: var(--gutter);
}

.lp-bar__actions {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex: 0 0 auto;
}

@media (max-width: 400px) {
  .lp-bar { padding-inline: var(--s-3); }
}

.lp-wordmark {
  font-family: var(--ff-display);
  font-size: var(--fs-wordmark);
  letter-spacing: -.02em;
  color: #fff;
  line-height: 1;
  min-width: 0;
  overflow: hidden;
}

.lp-wordmark em {
  font-style: normal;
  color: var(--sp-lime);          /* fallback where background-clip:text is unsupported */
  background: var(--spectrum);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* Same trade as the app bar: below 480px the right-hand controls leave under
   80px, and the full wordmark needs ~140. The mark keeps the spectrum on its
   second letter so the brand cue survives; the accessible name does not
   shorten. */
.lp-wordmark__full { display: none; }
.lp-wordmark__mark { display: inline; }

@media (min-width: 480px) {
  .lp-wordmark__full { display: inline; }
  .lp-wordmark__mark { display: none; }
}

/* theme toggle — design.md §7.2b, raw ramp only, because it sits on ink */
.lp-theme {
  display: flex;
  align-items: center;
  background: rgba(255,255,255,.09);
  border-radius: var(--r-pill);
  padding: 3px;
}

.lp-theme__opt {
  position: relative;
  display: grid;
  place-items: center;
  width: 44px;
  height: 32px;
  border-radius: var(--r-pill);
  color: var(--n-500);            /* 5.3:1 on ink */
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}

/* reads as 32px, hits as 44px */
.lp-theme__opt::after { content: ""; position: absolute; inset: -6px 0; }

.lp-theme__opt svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Fill plus stroke weight, never hue — "which theme" is not one of the five
   meanings, so this control stays neutral. */
.lp-theme__opt[aria-pressed="true"] { background: rgba(255,255,255,.16); color: #fff; }
.lp-theme__opt[aria-pressed="true"] svg { stroke-width: 2.3; }
.lp-theme__opt:focus-visible { outline-color: var(--sp-teal); }

/* the bar's own CTA — hidden on phones, where the hero button is one scroll
   away and two pills plus a wordmark do not fit */
.lp-bar__cta {
  display: none;
  font-size: var(--fs-label);
  font-weight: 700;
  color: var(--text-on-accent);
  background: var(--accent-gradient);
  padding: 9px 16px;
  border-radius: var(--r-pill);
  white-space: nowrap;
  transition: transform var(--t-fast) var(--ease), filter var(--t-fast) var(--ease);
}

.lp-bar__cta:active { transform: scale(.96); filter: brightness(1.1); }
.lp-bar__cta:focus-visible { outline-color: var(--sp-teal); }

@media (min-width: 620px) {
  .lp-bar__cta { display: inline-block; }
}

/* ----------------------------------------------------------------- rule --
   design.md §7.3 — the signature band, the seam between chrome and content.
   Sticks directly under the bar exactly as it does in the app. */
.lp-rule {
  position: sticky;
  /* env() first so an installed/notched context doesn't overlap the bar underneath it. */
  top: calc(56px + env(safe-area-inset-top, 0px));
  z-index: 20;
  height: 8px;
  background-image:
    repeating-linear-gradient(90deg, var(--n-050) 0 1px, transparent 1px 8px),
    repeating-linear-gradient(90deg, var(--n-050) 0 1.5px, transparent 1.5px 40px),
    var(--spectrum);
  background-size: 100% 3px, 100% 6px, 100% 100%;
  background-repeat: no-repeat;
  transform-origin: left center;
  animation: lp-draw 520ms var(--ease) both;
}

@keyframes lp-draw { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* -------------------------------------------------------------- sections -- */
.lp-section { padding: var(--s-8) var(--gutter); }

.lp-section__inner {
  max-width: var(--lp-max);
  margin-inline: auto;
}

@media (min-width: 900px) {
  .lp-section { padding-block: 88px; }
}

.lp-eyebrow {
  display: flex;
  align-items: center;
  gap: 7px;
  font-family: var(--ff-data);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 0 0 var(--s-3);
}

/* The dot carries the section's axis colour where the section owns one, and stays
   neutral where it does not — a hue is a meaning, so a section with no axis gets no
   hue. No glow: that is a FilterControl affordance (§7.4), not a page decoration. */
.lp-eyebrow::before {
  content: "";
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--axis, var(--text-faint));
}

/* the one section that is about all three axes at once takes all five hues */
.lp-eyebrow--spectrum::before { background: var(--spectrum); }

.lp-h2 {
  font-size: clamp(1.5rem, 1.15rem + 1.6vw, 2.25rem);
  line-height: 1.15;
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--text-strong);
  max-width: 20ch;
  text-wrap: balance;
}

.lp-lede {
  margin: var(--s-4) 0 0;
  color: var(--text-muted);
  max-width: var(--lp-prose);
}

/* ------------------------------------------------------------------ hero --
   Copy left, instrument right. One column until the illustration has room to
   be worth its width. */
.lp-hero {
  padding-top: var(--s-7);
  display: grid;
  gap: var(--s-7);
  align-items: center;
}

@media (min-width: 900px) {
  .lp-hero {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
    gap: var(--s-8);
    padding-top: 72px;
  }
}

/* The only element on the page in the display face besides the wordmark —
   design.md §4. clamp() is fine here: this is a headline, not a mono readout,
   so fractional pixels cost nothing. */
.lp-hero__title {
  font-family: var(--ff-display);
  font-weight: 400;              /* Archivo Black ships one weight; 700 would synthesise */
  /* Lowered min from 2.125rem: at 320px the old floor crowded the badge row below it. */
  font-size: clamp(1.875rem, 1.35rem + 3.9vw, 4rem);
  line-height: 1.02;
  letter-spacing: -.03em;
  color: var(--text-strong);
  margin: 0;
  text-wrap: balance;
}

.lp-hero__title em {
  font-style: normal;
  color: var(--sp-lime);          /* fallback, as in the wordmark */
  background: var(--spectrum);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.lp-hero__sub {
  margin: var(--s-5) 0 0;
  font-size: clamp(1rem, .95rem + .35vw, 1.1875rem);
  line-height: 1.5;
  color: var(--text-muted);
  max-width: 46ch;
}

.lp-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
  margin-top: var(--s-6);
}

/* Violet is action. The gradient runs violet → indigo, never violet → teal:
   it carries white text, and white on teal is 1.8:1 (design.md §3). */
.lp-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-height: 48px;
  padding: 0 var(--s-6);
  border-radius: var(--r-pill);
  font-size: var(--fs-body);
  font-weight: 700;
  transition: transform var(--t-fast) var(--ease), filter var(--t-fast) var(--ease),
              background var(--t-fast) var(--ease);
}

.lp-btn:active { transform: scale(.97); }

.lp-btn--primary {
  background: var(--accent-gradient);
  color: var(--text-on-accent);
  box-shadow: var(--e-glow);       /* the one glow on the page, as in the app */
}

.lp-btn--primary:active { filter: brightness(1.1); }

.lp-btn--primary svg {
  width: 16px; height: 16px;
  fill: none; stroke: currentColor;
  stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round;
}

.lp-btn--ghost {
  background: var(--bg-surface);
  color: var(--text-strong);
  border: 1px solid var(--border-hair);
}

.lp-btn--ghost:hover { background: var(--bg-raised); }

.lp-note {
  margin: var(--s-4) 0 0;
  font-family: var(--ff-data);
  font-size: var(--fs-data);
  letter-spacing: .04em;
  color: var(--text-faint);
}

/* ---------------------------------------------------------- the instrument --
   A feed tile at hero size. Square, radius 0, overlays exactly where §7.5 puts
   them — the page shows the product rather than describing it. */
.lp-instrument {
  position: relative;
  margin: 0;            /* it is a <figure> */
  width: 100%;
  max-width: 460px;
  margin-inline: auto;
  aspect-ratio: 1;
  overflow: hidden;
  background: var(--bg-raised);
  box-shadow: var(--e-1);
  animation: lp-rise var(--t-base) var(--ease) 120ms both;
}

@keyframes lp-rise {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

.lp-instrument__scene {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;      /* the asset is already square; this is belt and braces */
}

/* Measurement chip — the one overlay with a solid ground, so it survives a
   blown-out sky. Stepped up from the grid's 11px to match a 460px tile. */
.lp-instrument__scale {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 2;
  font-family: var(--ff-data);
  font-size: 1rem;
  font-weight: 500;
  color: #fff;
  background: rgba(0,0,0,.6);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  padding: 5px 10px;
  border-radius: 7px;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.10);
}

.lp-instrument__scale u {
  text-decoration: none;
  color: var(--sp-teal);          /* teal is the reference axis */
  font-size: .8125rem;
  text-transform: uppercase;
  margin-left: 5px;
}

.lp-instrument__stats {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-1);
  padding: 34px 10px 10px;
  background: var(--scrim);        /* scrim only — no full-tile tint, ever */
  font-family: var(--ff-data);
  font-size: .8125rem;
  color: #fff;
}

.lp-stat {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  text-shadow: 0 1px 2px rgba(0,0,0,.8);
}

.lp-stat svg { width: 14px; height: 14px; flex: 0 0 auto; }
.lp-stat--like svg { fill: var(--sp-coral); }   /* coral is like */
.lp-stat--talk svg { fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linejoin: round; opacity: .92; }
.lp-stat--vs svg { fill: currentColor; opacity: .92; }

/* ---------------------------------------------------------- hero visual ----
   The tile plus the badge row under it. Badges are not on the tile itself —
   tiles carry no badges in the app (§7.5) — so this wrapper is what centres
   the two as one column. */
.lp-hero__visual {
  display: grid;
  justify-items: center;
  width: 100%;
  max-width: 460px;
  margin-inline: auto;
}

/* --------------------------------------------------------------- badges ----
   Shared by the hero row (static — "this post earned both") and the capture
   panel's live row (real state, updated as the level guide moves). */
.lp-badges,
.lp-capture__badges {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
  margin-top: var(--s-3);
}

.lp-hero__visual .lp-badges { justify-content: center; }

@media (min-width: 900px) {
  .lp-hero__visual .lp-badges { justify-content: flex-start; }
}

.lp-capture__badges { justify-content: center; }

/* A solid lime fill, same pattern PostDetail.razor.css's own .post-detail__badge
   uses (design.md §7.11) — the RAW --sp-lime, not the semantic --safe: --safe is
   darkened for light-theme text/icon use, which would read dark-on-dark paired
   with the constant --text-on-bright here. */
.lp-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 28px;
  padding: 0 var(--s-3);
  border-radius: var(--r-pill);
  background: var(--sp-lime);
  color: var(--text-on-bright);
  font-size: var(--fs-label);
  font-weight: 700;
}

.lp-badge svg {
  width: 14px; height: 14px; flex: 0 0 auto;
  stroke: currentColor; stroke-width: 2.6; fill: none;
}

/* Unearned: a neutral outline pill, the check glyph faded rather than gone —
   the non-colour cue §9 asks for, on top of the colour swap. */
.lp-badge[data-earned="false"] {
  background: var(--bg-raised);
  color: var(--text-muted);
  box-shadow: inset 0 0 0 1px var(--border-hair);
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}

.lp-badge[data-earned="false"] svg { opacity: .35; }

.lp-badges__note,
.lp-capture__badges-hint {
  font-family: var(--ff-data);
  font-size: var(--fs-micro);
  letter-spacing: .04em;
  color: var(--text-faint);
}

/* ---------------------------------------------------- capture demo --------
   design.md §7.10/§7.11: this panel mirrors /post (Pages/Post.razor) — keep
   the two in step. The level-guide rules below and the orientation constants
   in the capture script are copies of Post.razor.css / capture.js, not a
   reinterpretation, so the two views agree on what "level" and "tilt" mean.

   The viewfinder runs a LIVE getUserMedia stream, but only after an explicit
   click. A landing page that fires a permission prompt on load is the hostile
   version of this, and Safari wants a user gesture regardless. Every failure
   path — refused, no camera, insecure context, ancient browser — falls back
   to the same drawn idle state, so the panel is never broken, only quieter.

   The stream is local. Nothing is captured, uploaded or sent anywhere, and
   the tracks are stopped on toggle-off and on pagehide.

   The shutter takes the accent gradient but NOT the violet bloom: §7.10 gives
   the bloom to the one live post button, and this page already spends it on
   the hero CTA. Two glows would be spending boldness twice. */
.lp-capture {
  background: var(--bg-surface);
  border: 1px solid var(--border-hair);
  border-radius: var(--r-lg);      /* §5: --r-lg is the sheet radius */
  box-shadow: var(--e-2);          /* §5: --e-2 is the sheet elevation */
  padding: var(--s-4);
  display: grid;
  gap: var(--s-3);
  max-width: 420px;
  margin-inline: auto;
  width: 100%;
}

.lp-capture__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  flex-wrap: wrap;
}

.lp-capture__label {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 7px;
  font-family: var(--ff-data);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* teal, because the thing this view exists to frame is the reference object */
.lp-capture__label::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--axis-reference);
}

.lp-capture__toggle {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 44px;                /* §9 floor, not shrunk for pointers */
  padding: 0 var(--s-3);
  border-radius: var(--r-pill);
  border: 1px solid var(--border-hair);
  background: var(--bg-raised);
  font-size: var(--fs-label);
  font-weight: 700;
  color: var(--text-strong);
  white-space: nowrap;
  transition: background var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}

.lp-capture__toggle:hover { background: var(--bg-surface); }
.lp-capture__toggle:active { transform: scale(.97); }

.lp-capture__toggle svg {
  width: 16px; height: 16px; flex: 0 0 auto;
  fill: none; stroke: currentColor;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}

/* nothing to toggle when the browser cannot do it at all */
.lp-capture[data-state="unsupported"] .lp-capture__toggle { display: none; }

/* ----- viewfinder ----- */
.lp-capture__view {
  position: relative;
  aspect-ratio: 4 / 5;             /* matches /post's own on-device output ratio */
  overflow: hidden;
  border-radius: var(--r-lg);
  background: var(--bg-raised);
  display: grid;
  place-items: center;
}

.lp-capture[data-state="idle"] .lp-capture__view { cursor: pointer; }

.lp-capture__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: none;
}

.lp-capture[data-state="live"] .lp-capture__video { display: block; }
.lp-capture[data-state="live"] .lp-capture__idle { display: none; }

/* the front camera is previewed mirrored, the way every camera app shows it;
   the attribute lives on the video itself, as in capture.js */
.lp-capture__video[data-facing="user"] { transform: scaleX(-1); }

.lp-capture__idle {
  display: grid;
  justify-items: center;
  gap: var(--s-2);
  padding: var(--s-4);
  text-align: center;
  color: var(--text-faint);
}

.lp-capture__idle svg {
  width: 34px; height: 34px;
  fill: none; stroke: currentColor;
  stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round;
}

.lp-capture__idle p {
  margin: 0;
  font-family: var(--ff-data);
  font-size: var(--fs-micro);
  letter-spacing: .08em;
  text-transform: uppercase;
}

/* corner brackets — the measuring cue, in the reference hue */
.lp-capture__frame { position: absolute; inset: 12px; pointer-events: none; }

.lp-capture__frame i {
  position: absolute;
  width: 20px; height: 20px;
  border: 2px solid var(--axis-reference);
}

.lp-capture__frame i:nth-child(1) { top: 0; left: 0; border-right: 0; border-bottom: 0; border-top-left-radius: 4px; }
.lp-capture__frame i:nth-child(2) { top: 0; right: 0; border-left: 0; border-bottom: 0; border-top-right-radius: 4px; }
.lp-capture__frame i:nth-child(3) { bottom: 0; left: 0; border-right: 0; border-top: 0; border-bottom-left-radius: 4px; }
.lp-capture__frame i:nth-child(4) { bottom: 0; right: 0; border-left: 0; border-top: 0; border-bottom-right-radius: 4px; }

/* ----- tilt / level guide — copied from Post.razor.css's .cap__level* rules
   (design.md §7.11 v0.22, v0.23), renamed to this panel's own class prefix.
   The [data-available="prompt"] "tap for level" rules are left out: this page
   doesn't run the iOS auto-open path that needs them (v0.24). */
.lp-capture__level {
  position: absolute;
  top: 44px;
  left: 50%;
  transform: translateX(-50%);
  width: 96px;
  height: 96px;
  display: none;
  place-items: center;
  pointer-events: none;
}

.lp-capture[data-state="live"] .lp-capture__level[data-available="true"] { display: grid; }

.lp-capture__level-upright,
.lp-capture__level-flat {
  grid-area: 1 / 1;
  position: relative;
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
}

.lp-capture__level[data-mode="flat"] .lp-capture__level-upright { display: none; }
.lp-capture__level[data-mode="upright"] .lp-capture__level-flat { display: none; }

/* upright: crosshair / horizon. No transition on the rotate — it has to track
   the sensor in real time, not ease toward it. The dark halo on every stroke
   is what keeps the guide readable over a bright or busy viewfinder. */
.lp-capture__level-fixed,
.lp-capture__level-live {
  position: absolute;
  width: 64px;
  height: 3px;
  border-radius: 1.5px;
  background: var(--unsafe);
  filter: drop-shadow(0 0 2px rgba(0, 0, 0, .65));
}

.lp-capture__level-fixed { opacity: .5; }
.lp-capture__level-live { transform: rotate(var(--tilt-rot, 0deg)); }

.lp-capture__level[data-level="caution"] .lp-capture__level-fixed,
.lp-capture__level[data-level="caution"] .lp-capture__level-live { background: var(--caution); }
.lp-capture__level[data-level="level"] .lp-capture__level-fixed,
.lp-capture__level[data-level="level"] .lp-capture__level-live { background: var(--safe); }

.lp-capture__level-pivot {
  position: absolute;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 3px solid var(--unsafe);
  background: transparent;
  filter: drop-shadow(0 0 2px rgba(0, 0, 0, .65));
}

.lp-capture__level[data-level="caution"] .lp-capture__level-pivot { border-color: var(--caution); }
.lp-capture__level[data-level="level"] .lp-capture__level-pivot {
  border-color: var(--safe);
  background: var(--safe);
}

/* flat: bubble level */
.lp-capture__level-ring {
  position: absolute;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  border: 3px solid var(--unsafe);
  filter: drop-shadow(0 0 2px rgba(0, 0, 0, .65));
}

.lp-capture__level[data-level="caution"] .lp-capture__level-ring { border-color: var(--caution); }
.lp-capture__level[data-level="level"] .lp-capture__level-ring { border-color: var(--safe); }

.lp-capture__level-dot {
  position: absolute;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--unsafe);
  transform: translate(var(--tilt-x, 0px), var(--tilt-y, 0px));
  filter: drop-shadow(0 0 2px rgba(0, 0, 0, .65));
}

.lp-capture__level[data-level="caution"] .lp-capture__level-dot { background: var(--caution); }
.lp-capture__level[data-level="level"] .lp-capture__level-dot { background: var(--safe); }

/* A solid fill instead of bare colour on the video feed, same "invert
   colours" legibility fix as the strokes above. RAW --sp-coral/-amber/-lime,
   not the semantic tokens, for the same reason .lp-badge uses --sp-lime raw.
   The non-colour cue is the three-way weight ramp below, independent of hue. */
.lp-capture__level-label {
  position: absolute;
  top: 100%;
  margin-top: var(--s-1);
  padding: var(--s-1) var(--s-2);
  border-radius: var(--r-pill);
  font-family: var(--ff-data);
  font-size: var(--fs-micro);
  letter-spacing: .08em;
  text-transform: uppercase;
  font-weight: 500;
  background: var(--sp-coral);
  color: var(--text-on-bright);
}

.lp-capture__level[data-level="caution"] .lp-capture__level-label {
  background: var(--sp-amber);
  font-weight: 600;
}

.lp-capture__level[data-level="level"] .lp-capture__level-label {
  background: var(--sp-lime);
  font-weight: 700;
}

/* the 7.10 post button, minus the bloom — see the note at the top of this
   block. Hidden until the camera is live, so a link never looks like a
   capture control while nothing is showing. */
.lp-capture:not([data-state="live"]) .lp-capture__shutter { display: none; }

.lp-capture__shutter {
  position: absolute;
  left: 50%;
  bottom: var(--s-3);
  transform: translateX(-50%);
  z-index: 1;
  display: grid;
  place-items: center;
  width: 56px; height: 56px;
  border-radius: 50%;
  background: var(--accent-gradient);
  color: var(--text-on-accent);
  box-shadow: 0 0 0 1px rgba(255,255,255,.10);
  transition: transform var(--t-fast) var(--ease), filter var(--t-fast) var(--ease);
}

.lp-capture__shutter:active { transform: translateX(-50%) scale(.94); filter: brightness(1.12); }

.lp-capture__shutter-ring {
  width: 40px; height: 40px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 3px rgba(255,255,255,.55);
}

/* ----- item, reference — mirror Post.razor.css's .cap__item and .cap__ctl rules ----- */
.lp-capture__item {
  display: grid;
  gap: 6px;
}

.lp-capture__item-label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--ff-data);
  font-size: var(--fs-micro);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.lp-capture__item-label::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--axis-subject);
  box-shadow: 0 0 8px var(--axis-subject);
}

/* Chips copy the look of TagInput.razor.css's own .taginput__chip. */
.lp-capture__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}

.lp-capture__chips li {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 32px;
  padding: 0 var(--s-3);
  border-radius: var(--r-pill);
  border: 1px solid var(--border-hair);
  background: var(--bg-surface);
  font-size: var(--fs-label);
  font-weight: 600;
  color: var(--text-strong);
}

.lp-capture__chips li::before {
  content: "";
  width: 7px; height: 7px;
  margin-right: 2px;
  border-radius: 50%;
  background: var(--axis-subject);
  flex: 0 0 auto;
}

.lp-capture__ctl {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  min-height: 48px;
  padding: 0 var(--s-3);
  border-radius: var(--r-md);
  border: 1px solid var(--border-hair);
  background: var(--bg-surface);
}

.lp-capture__ctl-label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--ff-data);
  font-size: var(--fs-micro);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
}

.lp-capture__ctl-label::before {
  content: "";
  flex: 0 0 auto;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--obj, var(--axis-reference));
  box-shadow: 0 0 8px var(--obj, var(--axis-reference));
}

.lp-capture__ctl-value {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  font-size: var(--fs-label);
  font-weight: 700;
  color: var(--text-strong);
}

.lp-capture__ctl-value > span:first-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lp-capture__ctl-mm { font-weight: 500; color: var(--text-muted); }

.lp-capture__ctl-caret {
  width: 12px; height: 12px; flex: 0 0 auto;
  stroke: var(--text-muted);
  fill: none;
  stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round;
}

/* ----- control bar — just the flip button now; the shutter lives on the
   viewfinder itself, above ----- */
.lp-capture__bar {
  display: flex;
  justify-content: center;
}

.lp-capture__aux {
  display: grid;
  place-items: center;
  width: 44px; height: 44px;       /* §9 floor */
  border-radius: var(--r-pill);
  color: var(--text-muted);
}

.lp-capture__aux svg {
  width: 20px; height: 20px;
  fill: none; stroke: currentColor;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}

button.lp-capture__aux:disabled { opacity: .45; cursor: default; }

@media (hover: hover) and (pointer: fine) {
  button.lp-capture__aux:not(:disabled):hover { color: var(--text-strong); background: var(--bg-raised); }
}

.lp-capture__hint,
.lp-capture__note,
.lp-capture__status {
  margin: 0;
  font-family: var(--ff-data);
  font-size: var(--fs-micro);
  line-height: 1.5;
  letter-spacing: .04em;
  color: var(--text-faint);
  text-align: center;
}

.lp-capture__hint { color: var(--text-muted); }

/* Empty until something actually fails, so it never holds space it does not
   need. Coral is the blocked/unsafe hue, and it is TEXT here, so it reads from
   --unsafe, which carries a darkened light-theme variant. */
.lp-capture__status { color: var(--unsafe); }
.lp-capture__status:empty { display: none; }

/* ------------------------------------------------------- how it works ------
   A sequence, so it is numbered. The anti-goal in §2 is numbered markers on
   the FEED, which has no order; three steps genuinely do. */
/* base.css resets <ul> only, and these steps are a genuine <ol> */
.lp-steps {
  list-style: none;
  padding: 0;
  display: grid;
  gap: var(--s-4);
  margin: var(--s-7) 0 0;
}

@media (min-width: 760px) {
  .lp-steps { grid-template-columns: repeat(3, 1fr); gap: var(--s-5); }
}

.lp-step {
  background: var(--bg-surface);
  border: 1px solid var(--border-hair);
  border-radius: var(--r-md);
  padding: var(--s-5);
  box-shadow: var(--e-1);
}

/* one hue per step, carrying its meaning: subject, reference, feed action */
.lp-step__bar {
  height: 3px;
  width: 40px;
  border-radius: var(--r-pill);
  background: var(--axis);
  margin-bottom: var(--s-4);
}

.lp-step__n {
  font-family: var(--ff-data);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: .08em;
  color: var(--text-faint);
}

.lp-step__h {
  margin: var(--s-2) 0;
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--text-strong);
}

.lp-step__p { margin: 0; color: var(--text-muted); font-size: var(--fs-body); }

/* ------------------------------------------------------------- three axes --
   Replicas of the real FilterControl (§7.4) at the real dimensions. Static:
   this page cannot open a bottom sheet, so they are presentational and
   aria-hidden, with the three axes named in prose beside them. */
.lp-axes {
  display: grid;
  gap: var(--s-7);
  margin-top: var(--s-6);
  align-items: center;
}

@media (min-width: 900px) {
  .lp-axes { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s-8); }
}

.lp-controls { display: grid; gap: var(--s-3); }

/* Below 420px — and at 200% text zoom, which lands in the same place — three
   columns cannot hold a full object name, so the row stacks rather than
   truncating to nothing (§7.4). */
@media (min-width: 420px) {
  .lp-controls { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.lp-ctl {
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 3px;
  padding: 8px 10px;
  min-height: 56px;
  background: var(--bg-surface);
  border: 1px solid var(--border-hair);
  border-radius: var(--r-md);
}

.lp-ctl--sort { --axis: var(--axis-sort); }
.lp-ctl--subject { --axis: var(--axis-subject); }
.lp-ctl--reference { --axis: var(--axis-reference); }

.lp-ctl__label {
  display: flex;
  align-items: center;
  gap: 5px;
  font-family: var(--ff-data);
  font-size: var(--fs-micro);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.lp-ctl__label::before {
  content: "";
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--axis);
  box-shadow: 0 0 8px var(--axis);
}

.lp-ctl__value {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 4px;
  font-size: .78rem;
  font-weight: 700;
  color: var(--text-strong);
  min-width: 0;
}

.lp-ctl__value span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lp-ctl__value svg {
  width: 12px; height: 12px; flex: 0 0 auto;
  stroke: var(--text-muted); fill: none;
  stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round;
}

.lp-axes__list { margin: var(--s-5) 0 0; display: grid; gap: var(--s-4); }

/* Shared with .lp-feat (the #capture / #compare feature lists) — same grid,
   same dot, so a new section doesn't reinvent the axis-prose pattern. Only
   .lp-axis's dot gets the glow: a FilterControl affordance, not a page
   decoration, so a neutral .lp-feat dot stays flat. */
.lp-axis,
.lp-feat {
  display: grid;
  grid-template-columns: 7px 1fr;
  gap: var(--s-3);
  align-items: start;
}

.lp-axis::before,
.lp-feat::before {
  content: "";
  width: 7px; height: 7px;
  margin-top: 8px;
  border-radius: 50%;
  background: var(--axis);
}

.lp-axis::before { box-shadow: 0 0 8px var(--axis); }

.lp-axis b, .lp-feat b { color: var(--text-strong); font-weight: 700; }
.lp-axis p, .lp-feat p { margin: 2px 0 0; color: var(--text-muted); font-size: var(--fs-body); }

.lp-feats { display: grid; gap: var(--s-4); margin: var(--s-6) 0 0; }

/* --------------------------------------------------------------- splits ----
   Shared two-column layout for #capture and #compare: copy one side, a demo
   the other. Below 900px both stack copy-first, in DOM order — .lp-split--flip
   only reorders them once there is room to read across, not down, a page. */
.lp-split {
  display: grid;
  gap: var(--s-7);
  align-items: center;
}

.lp-split__copy, .lp-split__demo { min-width: 0; }

@media (min-width: 900px) {
  .lp-split {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--s-8);
  }

  .lp-split--flip .lp-split__demo { order: -1; }
}

/* ----------------------------------------------------------- editor demo --
   A presentational replica of DuelEditor.razor (§7.15) for #compare: two
   copies of the hero asset standing in for two different posts. */
.lp-editor { margin: 0; }

.lp-editor__canvas {
  position: relative;
  aspect-ratio: 4 / 5;
  background: #000;     /* the editor canvas is hard-coded #000, per §7.15 */
  overflow: hidden;
  width: 100%;
  max-width: 420px;
  margin-inline: auto;
}

.lp-editor__layer {
  position: absolute;
  top: 12%;
  width: 50%;
  display: block;
}

.lp-editor__layer--a { left: 0; }

/* outline shows which layer is "selected" in this static replica */
.lp-editor__layer--b {
  right: 0;
  transform: scaleX(-1);
  outline: 2px solid var(--axis-reference);
  outline-offset: -2px;
}

/* same look as .lp-instrument__scale, minus the unit */
.lp-editor__label {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 2;
  font-family: var(--ff-data);
  font-size: var(--fs-micro);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: #fff;
  background: rgba(0,0,0,.6);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  padding: 5px 10px;
  border-radius: 7px;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.10);
}

.lp-editor__bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  justify-content: center;
  margin-top: var(--s-3);
  max-width: 420px;
  margin-inline: auto;
}

.lp-editor__pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 40px;
  padding: 0 var(--s-3);
  border-radius: var(--r-pill);
  background: var(--bg-surface);
  border: 1px solid var(--border-hair);
  font-family: var(--ff-data);
  font-size: var(--fs-micro);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.lp-editor__pill svg {
  width: 16px; height: 16px;
  fill: none; stroke: currentColor;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}

/* "Move" is the one pressed tool in this static replica */
.lp-editor__pill--active { background: var(--bg-raised); color: var(--text-strong); }

/* ------------------------------------------------------- reference catalogue --
   Object chips. The dot takes a colour sampled from the object, which is the
   one sanctioned override of the axis colour (§7.4) — so these dots ARE the
   objects, not decoration. Labelled as objects: "Lighter", not a hashtag. */
.lp-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: var(--s-6);
}

.lp-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 14px;
  border-radius: var(--r-pill);
  background: var(--bg-surface);
  border: 1px solid var(--border-hair);
  font-family: var(--ff-data);
  font-size: var(--fs-label);
  color: var(--text-strong);
  white-space: nowrap;
}

.lp-chip::before {
  content: "";
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--obj);
  flex: 0 0 auto;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.25);
}

.lp-chip__mm {
  font-size: var(--fs-micro);
  letter-spacing: .06em;
  color: var(--text-faint);
}

/* the trailing chip is not an object, so it takes no dot */
.lp-chip--more { border-style: dashed; color: var(--text-muted); }
.lp-chip--more::before { display: none; }

/* ---------------------------------------------------------------- honesty -- */
.lp-cards {
  display: grid;
  gap: var(--s-4);
  margin-top: var(--s-7);
}

@media (min-width: 600px) {
  .lp-cards { grid-template-columns: repeat(2, 1fr); gap: var(--s-5); }
}

@media (min-width: 1024px) {
  .lp-cards { grid-template-columns: repeat(3, 1fr); }
}

/* The 4-card rules grid stays 2-up past 1024px too, so four cards never
   leave a 3+1 orphan row. Higher specificity than .lp-cards alone, so it
   wins over the 3-column rule above without !important. */
@media (min-width: 1024px) {
  .lp-cards.lp-cards--2up { grid-template-columns: repeat(2, 1fr); }
}

.lp-card {
  background: var(--bg-surface);
  border: 1px solid var(--border-hair);
  border-radius: var(--r-md);
  padding: var(--s-5);
}

.lp-card h3 {
  margin: var(--s-3) 0 var(--s-2);
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: -.01em;
}

.lp-card p { margin: 0; color: var(--text-muted); font-size: var(--fs-body); }

/* Neutral glyphs by default — these are rules of the pipeline or features,
   not one of the five meanings, so they take no spectrum hue. Two modifiers
   are the sanctioned exceptions: Likes (coral, it IS the like axis) and the
   level-semaphore rule card (--safe, it IS the semaphore). */
.lp-card__icon {
  width: 28px; height: 28px;
  fill: none; stroke: var(--text-strong);
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}

.lp-card__icon--like { stroke: var(--like); }
.lp-card__icon--safe { stroke: var(--safe); }

/* ------------------------------------------------------------- on the bench --
   Kept visibly separate from everything above, because these are not built
   yet and the page must not imply that they are. */
.lp-bench {
  margin-top: var(--s-7);
  border-top: 1px solid var(--border-hair);
  padding-top: var(--s-5);
  display: grid;
  gap: var(--s-4);
}

@media (min-width: 700px) { .lp-bench { grid-template-columns: repeat(3, 1fr); } }

.lp-bench__item { display: grid; gap: 4px; }

.lp-bench__tag {
  font-family: var(--ff-data);
  font-size: var(--fs-micro);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--axis);
}

.lp-bench__item p { margin: 0; color: var(--text-muted); font-size: var(--fs-body); }
.lp-bench__item b { color: var(--text-strong); }

/* ------------------------------------------------------------------- close -- */
.lp-close {
  max-width: var(--lp-max);
  margin-inline: auto;
  border-radius: var(--r-lg);
  border: 1px solid var(--border-hair);
  background: var(--bg-surface);
  box-shadow: var(--e-1);
  overflow: hidden;
}

/* the spectrum returns once, at the end, as the lid of the closing card. Its
   ticks are cut in the card's own surface tone, not the ink, so the band reads
   the same way in both themes. */
.lp-close__rule {
  height: 8px;
  background-image:
    repeating-linear-gradient(90deg, var(--bg-surface) 0 1px, transparent 1px 8px),
    repeating-linear-gradient(90deg, var(--bg-surface) 0 1.5px, transparent 1.5px 40px),
    var(--spectrum);
  background-size: 100% 3px, 100% 6px, 100% 100%;
  background-repeat: no-repeat;
}

.lp-close__body { padding: var(--s-7) var(--s-5); text-align: center; }

@media (min-width: 700px) { .lp-close__body { padding: var(--s-8); } }

.lp-close__h {
  margin: 0;
  font-size: clamp(1.375rem, 1.1rem + 1.3vw, 2rem);
  font-weight: 700;
  letter-spacing: -.02em;
  text-wrap: balance;
}

.lp-close__p {
  margin: var(--s-3) auto 0;
  max-width: 48ch;
  color: var(--text-muted);
}

.lp-close .lp-actions { justify-content: center; }

/* ------------------------------------------------------------------ footer -- */
.lp-footer {
  max-width: var(--lp-max);
  margin-inline: auto;
  padding: var(--s-7) var(--gutter) var(--s-8);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  border-top: 1px solid var(--border-hair);
}

.lp-footer__mark {
  font-family: var(--ff-display);
  font-size: 1.125rem;
  letter-spacing: -.02em;
  color: var(--text-strong);
}

.lp-footer__mark em {
  font-style: normal;
  color: var(--sp-lime);
  background: var(--spectrum);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.lp-footer__nav { display: flex; flex-wrap: wrap; gap: var(--s-4); }

.lp-footer__nav a {
  font-family: var(--ff-data);
  font-size: var(--fs-data);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding-block: 8px;
}

.lp-footer__nav a:hover { color: var(--text-strong); }

.lp-footer__legal {
  width: 100%;
  font-family: var(--ff-data);
  font-size: var(--fs-micro);
  letter-spacing: .04em;
  color: var(--text-faint);
}

/* ------------------------------------------------------------ wide screens --
   A wider content ceiling once there is room for it, plus the hero visual
   stepping up with it so it doesn't look stranded in a much wider column. */
@media (min-width: 1440px) {
  .lp { --lp-max: 1240px; }

  .lp-hero__visual, .lp-instrument { max-width: 520px; }
}

/* ---------------------------------------------------------------- ultrawide --
   §6: past --shell-max the body drops to the void tone and the page reads as a
   framed document rather than a wall of text. base.css already flips the body
   at 1600px; this keeps the landing's own ground on the canvas tone so the
   frame is legible. */
@media (min-width: 1600px) {
  .lp {
    max-width: var(--shell-max);
    margin-inline: auto;
    background: var(--bg-canvas);
    border-inline: 1px solid var(--border-hair);
    box-shadow: var(--e-2);
  }
}

/* base.css already kills every animation under reduced motion; these also drop
   the transform and opacity so nothing is left frozen mid-flight. */
@media (prefers-reduced-motion: reduce) {
  .lp-rule { transform: none; }
  .lp-instrument { opacity: 1; transform: none; }
}
