/* lot-extra.css — HAND-EDITED, and that is the whole reason it exists.
   ---------------------------------------------------------------------------
   `lot.css` is BUILT from `site/src/lot.src.css` by `npm run css`, so a rule
   written into it is lost on the next build. This sheet is the hand-editable
   layer that loads AFTER it and carries only what a later pass added on top of
   the built one. Load order is load-bearing: site.css, lot.css, then this.

   HOUSE LAW, OBSERVED HERE AS EVERYWHERE:
   - Borderless. Nothing below writes a `border`, a resting `outline`, or a
     `box-shadow` under 3px of spread. Separation is fill and spacing.
   - Tokens, not literals. Every colour and every rung is a `var(--lp-*)` that
     site.css already declares.
   - One accent, one meaning. Amber is "LotPost is waiting for you". It is the
     right hue for a QUEUE, which is a page-length picture of waiting, and it
     is not used below to mean anything else.
   - No type size is written as a literal px. The one exception is the mobile
     HEIGHT of a drawn cell, which is a picture's dimension and not type.

   Sections touched: #queue, #price, #how.
   -------------------------------------------------------------------------- */


/* =========================================================== #queue, ground

   THE PATTERN IS THE SUBJECT DRAWN AT PAGE SCALE. #queue is about a lot of
   cars standing in line for a slot, and the section behind them is a lined
   sheet: an amber hairline grid on the true-black ground at 4% and 3%, the
   same hue the day cells are lit in, so the pattern and the instrument on top
   of it are plainly the same picture.

   IT IS A ::before AND NOT A background ON THE SECTION for two reasons: the
   mask that fades it out at the edges would otherwise fade the section's own
   fill, and a pattern that tiles hard into the neighbouring section reads as a
   seam. `isolation: isolate` keeps the layer under the content without a
   z-index race. */
#queue {
  position: relative;
  isolation: isolate;
}

#queue::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    repeating-linear-gradient(90deg, rgba(242, 169, 59, 0.055) 0 1px, transparent 1px 88px),
    repeating-linear-gradient(0deg,  rgba(242, 169, 59, 0.035) 0 1px, transparent 1px 88px);
  /* Faded on every side, so the grid belongs to this section rather than
     running under the price cards below it. */
  -webkit-mask-image: radial-gradient(120% 90% at 50% 40%, #000 35%, transparent 78%);
  mask-image: radial-gradient(120% 90% at 50% 40%, #000 35%, transparent 78%);
  pointer-events: none;
}

/* The 88px cell is the desktop rhythm. On a phone it lands as four lines
   across the whole viewport, which reads as a ruled page rather than a
   texture, so the grid tightens with the column. */
@media (max-width: 767px) {
  #queue::before {
    background-image:
      repeating-linear-gradient(90deg, rgba(242, 169, 59, 0.05) 0 1px, transparent 1px 44px),
      repeating-linear-gradient(0deg,  rgba(242, 169, 59, 0.03) 0 1px, transparent 1px 44px);
  }
}

@media (prefers-reduced-motion: no-preference) {
  /* Nothing moves. The pattern is static on purpose: a drifting background
     behind a chart of posting times is a thing to read through, not with. */
}


/* ====================================================== #queue, on a phone

   THE TWO INSTRUMENTS ARE DRAWINGS WITH FIXED CELL HEIGHTS, and both were cut
   for a 1024px column. At 360 the clock's twenty-four cells come out about
   12px wide against a 44px height, which is a picket fence, and the two cards
   carry --lp-m6 of padding each on a 328px measure. Both are fixed by making
   the cell heights fluid rather than by hiding anything: every hour a dealer
   can pick is still on the strip. */
@media (max-width: 767px) {
  .lp-qrun,
  .lp-clock {
    padding: var(--lp-m5);
    gap: var(--lp-m3);
  }

  .lp-clock-bar {
    gap: 1px;
  }

  .lp-clock-bar i {
    height: clamp(26px, 7.5vw, 44px);
    border-radius: 3px;
  }

  .lp-clock-bar i.is-quiet {
    height: clamp(15px, 4.4vw, 26px);
  }

  /* The scale's three words are the only labels on the strip and they must not
     wrap: "midnight noon midnight" at 13px is 196px, which fits 328. */
  .lp-clock-scale {
    white-space: nowrap;
  }

  .lp-qday-cells i {
    height: clamp(22px, 6.5vw, 30px);
  }
}

/* The whole point of the pair at 360 is that it is ONE column of two cards and
   neither is scaled down to meet the other. Stated rather than inherited, so a
   later grid change upstream cannot quietly put them side by side at 400. */
@media (max-width: 1023px) {
  .lp-qpair {
    grid-template-columns: minmax(0, 1fr);
  }
}


/* ============================================================== #get, bento

   THE SECTION'S OWN HEADING IS "Three things it does. Three it will not." and
   until this pass the grid did not draw that sentence: the six cards ran a,b /
   c(full) / d,e / f(full), so the two groups were interleaved down four rows
   and the reader had to collect them by reading each card's tag. Measured at
   924px the section stood 1490px tall, and the two full-width cards were the
   two tallest things in it.

   THREE COLUMNS, TWO ROWS. Row one is the three It does, row two is the three
   It will not, which is the heading rendered as a layout. It also takes the
   section from four card rows to two.

   The full-bleed spans are released rather than re-tuned: `grid-column: auto`
   on all six, and the two cards that split into text-beside-drawing at 1024
   and 1280 stack their children again, because a two-column split inside a
   270px card is not a split. Source order is what wins here -- this sheet
   loads after lot.css and the selectors score the same, so the media queries
   in the built sheet do not need matching breakpoint for breakpoint. */
@media (min-width: 768px) and (max-width: 899px) {
  .lp-b-c,
  .lp-b-f {
    grid-column: auto;
  }
}

@media (min-width: 900px) {
  .lp-bento {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .lp-b-a,
  .lp-b-b,
  .lp-b-c,
  .lp-b-d,
  .lp-b-e,
  .lp-b-f {
    grid-column: auto;
  }

  .lp-b-a,
  .lp-b-c {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto 1fr;
    align-items: start;
  }

  .lp-b-c .lp-bpanel,
  .lp-b-a .lp-bpanel {
    grid-area: auto;
  }

  /* THE PANEL HEAD IS A ROW ONLY WHEN THE ROW FITS. `.lp-bptop` is a flex pair
     -- a label and a count -- cut for the 400px+ form of .lp-b-a; in a 272px
     card its two children measure 116 + 12 + 58 = 186 against a 218px content
     box with no slack, so both wrap at max-content and the head reads
     "EVERY BOX / FILLED" beside "18 OF / 18". A machine-face figure split
     mid-value is the "Qu" defect this page's own notes record.
     Stacked, not nowrapped: nowrap keeps the count whole and leaves the label
     wrapping, which is half a fix. */
  .lp-bptop {
    display: grid;
    justify-items: start;
    gap: 2px;
  }

  .lp-bptop b {
    white-space: nowrap;
  }

  .lp-bcard {
    padding: var(--lp-m5);
  }

  /* THE CHIP ROW'S NOWRAP WAS SAFE ONLY BECAUSE THE CARD WAS 871px WIDE.
     lot.css sets `.lp-bchips` to `flex-wrap: nowrap` from 768 for the
     full-bleed form of .lp-b-c; three of core/pace.mjs's cap chips measure
     370px, so in a 272px card the row sized its parent's auto track to
     max-content and painted 98px past .lp-wrap -- real bleed behind
     `overflow-x: clip`, which is proof/typeset.mjs check 1's whole subject and
     the trap this card's own comment quotes.
     The narrow form lot.css already ships below 768 is the right one here: a
     STACK, not a wrapped row, because Law 9 bans a chip row that wraps. */
  .lp-bchips {
    display: grid;
    justify-items: start;
  }

  /* And the belt to that braces: a grid item's `min-width` is auto, so any
     max-content child can blow the track again. Zero means the card's own
     width wins whatever lands inside it. */
  .lp-bcard-txt,
  .lp-bcard > * {
    min-width: 0;
  }
}

/* THE TWO HALVES ARE TWO FILLS, WHICH IS WHAT MAKES THE GROUPING READABLE
   WITHOUT A LABEL. Every card was --lp-surface, so "does" and "will not" were
   distinguished only by the words in the tag. The refusals step DOWN the
   surface ladder to the recessed rung -- a thing the product holds back is
   quieter than a thing it performs -- and their tag and their drawn rows step
   up to --lp-surface-3 so the ladder inside the card is preserved rather than
   flattened. Fill and spacing, never a rim. */
.lp-bcard-not {
  background: var(--lp-surface-2);
}

/* ONLY THE GLYPH TILE STEPS UP, NEVER THE LABEL. lot.css gives that tile
   --lp-surface-2, which is now the card's own fill, so the mark had nothing to
   sit on; the fix is the next rung of the ladder under the 34px tile and
   nothing behind the words. A fill behind "IT WILL NOT" is the light grey slab
   this repo's own stylesheets warn about twice -- two words wearing a chip
   read as a control nobody can press. */
.lp-bcard-not .lp-btag-i {
  background: var(--lp-surface-3);
}

.lp-bcard-not .lp-bnot-r {
  background: var(--lp-surface-3);
}

/* The drawings were cut for a card half the page wide. At a third of it they
   are the same pictures at the same proportions, three rungs shorter. */
.lp-bcells i {
  height: 14px;
}

.lp-bday-bars i {
  height: 24px;
}

.lp-bnot-r {
  min-height: 34px;
}

.lp-bform,
.lp-bday {
  padding: var(--lp-m4);
}


/* ==================================================== section headings, ink

   FLAT INK, 2026-09-18. The design shipped these h2s as a top-lit wash --
   `background-clip: text` over an ink-to-ink-2 gradient with `color:
   transparent` under it. It came out on arrival. Clipped text computes its
   colour as `transparent`, so site/proof.mjs's contrast probe reads every one
   of these headings at 1:1 against the black ground and fails it, nine pairs
   in each scheme. The wash's own comment called gradient text a flat ban in
   this house and then made an exception for itself; the ban wins. One token,
   the same one the h1 is set in. */
.lp-sec .lp-h2 { color: var(--lp-ink); }


/* ==================================================== #studio, the job chips

   THE CHIPS ARE PRESSABLE NOW, so they have to look it. They were drawn as
   labels inside an aria-hidden picture; each one loads a different gallery
   behind the stage, which makes them controls, and a control with no hover and
   no focus ring is a control a keyboard cannot find.

   Fill on hover, a 3px halo on focus. Both are the house's own devices: the
   halo is never under 3px of spread (see DESIGN.md, The Halo Not a Rim Rule)
   and the at-rest state gains nothing at all. */
.lp-edit-job {
  transition: background-color 180ms ease;
}

@media (prefers-reduced-motion: reduce) {
  .lp-edit-job {
    transition-duration: 0ms;
  }
}

@media (hover: hover) {
  .lp-edit-job:not(.is-on):hover {
    background: var(--lp-surface-3);
  }
}

.lp-edit-job:focus-visible {
  outline: 0;
  box-shadow: 0 0 0 3px var(--lp-accent-60);
}

/* The section is the fourth on the page now rather than the fifth, which puts
   the modal in front of a reader who has just been told what the product does
   and has not yet been told the price. It carries the page's heaviest drawing,
   so the stage gets the top of the lift ladder and its own contained ground --
   a picture of a modal wants to look like it is over something. */
.lp-edit {
  box-shadow: var(--lp-lift-3);
}


/* ============================================================ #price, cards

   THE THREE BUTTONS LINE UP. That is the single change that makes a price
   table read as priced rather than assembled: the cards carry 4, 4 and 5
   feature lines, so before this the calls to action sat at three different
   heights and the eye read the middle one as a different KIND of thing rather
   than the recommended one. The slack goes into the list's row, which is the
   only row on the card whose length is content and not design. */
.lp-plan {
  display: grid;
  grid-template-rows: auto auto auto auto 1fr auto;
  align-content: start;
}

.lp-plan-list {
  align-self: start;
}

/* MONEY IN TABULAR FIGURES. Archivo was chosen for this product's numbers
   specifically because its tabular-nums measured 0.00px of spread (see
   DESIGN.md, Typography), and a price is the one figure on the page a reader
   compares down a column. $49 / $99 / $149 with proportional digits do not
   align on the dollar sign. */
.lp-plan-fig b,
.lp-matrix .lp-val {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

.lp-plan-fig b {
  letter-spacing: -0.02em;
}

/* THE LEAD CARD IS LIT, NOT RIMMED. An accent wash pooled behind its head,
   drawn as a radial stop on the card's own background so it is a fill and not
   an edge, plus the next rung of the lift ladder so it sits above its two
   neighbours in the same plane they share. */
.lp-plan-lead {
  background-image: radial-gradient(120% 70% at 50% 0%, var(--lp-accent-12) 0%, transparent 62%);
  box-shadow: var(--lp-lift-2);
}

/* The date under each figure is a qualifier and reads as one: quiet, and on
   the same line rhythm in all three cards so the feature lists start level. */
.lp-plan-when {
  color: var(--lp-muted);
  min-height: 1.6em;
}

@media (max-width: 767px) {
  .lp-plan {
    padding: var(--lp-m5);
  }
}


/* =========================================================== #price, matrix

   A COMPARISON TABLE IS READ ACROSS, so the row label has to stay in front of
   the answer when the table is wider than the reading column. The label column
   is stuck to the inline start and carries the surface fill it sits on, which
   is what stops the yes/no marks scrolling under a transparent cell.
   The wrap is the scroller; the table itself is untouched. */
.lp-matrix-wrap {
  overflow-x: auto;
  overscroll-behavior-inline: contain;
}

.lp-matrix th[scope="row"] {
  position: sticky;
  inset-inline-start: 0;
  background: var(--lp-surface);
  z-index: 1;
}

.lp-matrix thead th {
  font-variant-numeric: tabular-nums;
}

/* The caption is the table's own title and was set at the same weight as its
   headers, which made the first row read as part of the head. */
.lp-matrix-cap {
  color: var(--lp-ink-2);
  text-align: start;
}


/* ================================================== #price, matrix on a phone

   THE TABLE IS NO LONGER HIDDEN UNDER 768. lot.css sets `.lp-matrix-wrap` to
   display:none there and the reasoning in index.html is sound about one thing
   -- a twelve-row four-column grid at 360 is a table people pinch, not read.
   So it is not shown as a table: each row becomes its own small card, the row
   label is its heading, and the three answers sit under it as label-and-value
   pairs. The plan names come from the `data-c` attribute the markup already
   carries on every cell, which is what that attribute was put there for.

   NOTHING IS RE-WORDED AND NO FIGURE ARRIVES. The yes/no marks keep their
   .lp-vh text, so a screen reader reads "Pro, yes" here exactly as it reads
   "Pro, yes" from the desktop table. */
@media (max-width: 767px) {
  .lp-matrix-wrap {
    display: block;
    margin-block-start: var(--lp-m7);
  }

  .lp-matrix,
  .lp-matrix thead,
  .lp-matrix tbody,
  .lp-matrix tr,
  .lp-matrix th,
  .lp-matrix td {
    display: block;
    width: auto;
  }

  /* The head row is three plan names with no row label to sit against; the
     cards below name their own plans. */
  .lp-matrix thead {
    display: none;
  }

  .lp-matrix tbody tr {
    margin-block-end: var(--lp-m3);
    padding: var(--lp-m4);
    border-radius: var(--lp-r-in);
    background: var(--lp-surface);
  }

  /* The zebra and the lit Pro column are both desktop devices for reading
     across a wide row. Down here every card is one row, so they only muddy
     which plan is which. */
  .lp-matrix tbody tr:nth-child(odd) th,
  .lp-matrix tbody tr:nth-child(odd) td,
  .lp-matrix td.is-lead {
    background: transparent !important;
  }

  .lp-matrix tbody th[scope="row"] {
    position: static;
    padding: 0 0 var(--lp-m3);
    color: var(--lp-ink);
    font-weight: 600;
  }

  .lp-matrix tbody td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--lp-m3);
    min-height: 34px;
    padding: 0;
    text-align: start;
  }

  .lp-matrix tbody td::before {
    content: attr(data-c);
    color: var(--lp-muted);
    font-size: var(--lp-mt-small);
    letter-spacing: var(--lp-track-label);
  }

  /* Pro is still the recommended rung; down here it is said with the accent
     ink on its own name rather than with a lit column. */
  .lp-matrix tbody td.is-lead::before {
    color: var(--lp-accent-ink);
    font-weight: 700;
  }
}


/* ============================================ the hero headline, three states

   THE DESIGN SHIPPED A ROTATOR WITH NOTHING TO DRIVE IT, 2026-09-18. The h1
   carries three `.lp-h1-line` variants, one of them marked `is-on`, and
   `lp-h1-line`, `lp-h1-half`, `lp-h1-em` and `lp-h1-lit` appear in no sheet
   and no script in this repo. So all three painted at once, stacked: ten lines
   at 360 against a cap of four, and a hero column the deck could not sit under.
   The bundle's own brief says why -- interactions prototyped in the design copy
   are stripped on export because the repo page has no script for them. This is
   that script's sheet half.

   ONE GRID CELL, NOT ABSOLUTE POSITIONING. All three variants share row 1 /
   column 1, so the h1 reserves the height of the TALLEST variant and the deck
   under it never moves when the headline turns. Absolute children would
   collapse the h1 to zero and put the deck through it.

   `visibility`, NOT OPACITY ALONE. An opacity-0 variant is still in the
   accessibility tree and still in `innerText`, which would hand a screen
   reader and site/seo-proof.mjs three different headlines joined end to end.
   Hidden means hidden; the delay on the way out is what lets the crossfade
   finish first. */
.lp-h1 {
  display: grid;
  /* minmax(0, 1fr), NOT the default `auto`. An auto grid column is at least
     its widest item's min-content, and the variants carry `inline-size: 100%`
     halves whose percentage resolves against an indefinite column -- which
     pushed the whole hero column to 384px inside a 360px phone and took eleven
     boxes over the edge with it. A zero floor lets the column be the viewport. */
  grid-template-columns: minmax(0, 1fr);
}
.lp-h1-line {
  grid-area: 1 / 1;
  min-inline-size: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.6s ease, visibility 0s linear 0.6s;
}
.lp-h1-line.is-on {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.6s ease, visibility 0s linear 0s;
}

/* The two emphasis inks the design set per variant. Accent on the word that
   carries the promise, ink on the word that names the reader. Flat tokens: the
   h1 is the page's one searchable sentence and gradient text is banned here. */
.lp-h1-em  { color: var(--lp-accent-ink); }
.lp-h1-lit { color: var(--lp-ink); }

/* Reduce stops the turn outright -- lot.js never starts the timer -- so the
   transition has nothing to run and is cut here too, which is what
   site/proof.mjs reads when it asks for a 0s longest transition. */
@media (prefers-reduced-motion: reduce) {
  .lp-h1-line, .lp-h1-line.is-on { transition: none; }
}


/* ================================================ the hero eyebrow, at 360

   `.lp-hero-who` is set `white-space: nowrap` so the line and its glyph read
   as one pill. A nowrap line has a min-content as wide as the sentence, and at
   360 that pushed `.lp-hero-in` to 384px and took the whole hero column --
   eleven boxes, h1 to art -- past the viewport edge. The pill keeps its one
   line everywhere it fits and is allowed to wrap on the narrowest phones,
   which is the only width where it cannot. */
@media (max-width: 480px) {
  .lp-hero-who { white-space: normal; text-align: start; }
}

/* THE MARK DOES NOT GROW WITH THE LINE. `.lp-who-mk` carries no width of its
   own, and an inline SVG with no width fills the box it is given: once the
   pill was allowed to wrap to three lines at 360 the glyph stretched to 120px
   square beside them. It is an 18px mark at every width, and `flex: none` so
   the wrapped text never pulls on it again. */
.lp-who-mk {
  inline-size: 18px;
  block-size: 18px;
  flex: none;
}


/* ============================================ the hover lift, under reduce

   The four tilted panels declare `transition: transform .45s` in their own
   inline style, which no sheet can lower, so site/proof.mjs read 0.45s as the
   page's longest transition under `prefers-reduced-motion: reduce`. The
   selector is the attribute that marks exactly those elements: site/lot.js
   wires no hover at all under reduce, so there is nothing left for the
   transition to carry and it comes to 0s here. */
@media (prefers-reduced-motion: reduce) {
  [style-hover] { transition: none !important; }
}


/* ============================================ #how, the flip row's columns

   `.lp-howrow-flip` marks a row whose panel should sit on the left with the
   copy on the right, reversing the section's default copy-left/panel-right
   order (requested for Step 01). `order` on the two direct children swaps
   them visually without touching the DOM, so the copy still reads first for
   anyone not seeing the layout. */
.lp-howrow-flip > .lp-stepcopy { order: 2; }
.lp-howrow-flip > .lp-stepcopy ~ div { order: 1; }

/* THE FLIP IS A TWO-COLUMN IDEA AND IT ENDS WITH THE SECOND COLUMN. Stacked,
   `order` put the panel ABOVE its own heading on the two flipped rows, so a
   reader scrolling a phone met step two's screenshot before anything said
   what step two was, and the four steps alternated picture-first,
   copy-first. Measured: the rows hold two columns from 1146px up. */
@media (max-width: 1145px) {
  .lp-howrow-flip > .lp-stepcopy,
  .lp-howrow-flip > .lp-stepcopy ~ div { order: 0; }
}


/* ==================================================== #how, the phone stack

   AT 360 THE PAGE WAS 16,578 CSS px TALL and site/proof.mjs could not capture
   it: a texture tops out at 16,384, so the check that reads the full-page slice
   was measuring a page it could not see whole. `#how` alone was 4,042 of those
   pixels, three step rows that each keep their desktop air on a phone.

   The air comes off the joins, not off the copy: the gap between rows and the
   lead-in above each one. `!important` because both values are inline on the
   elements the design exported, and an inline declaration is the one thing a
   sheet cannot outrank any other way. */
@media (max-width: 480px) {
  .lp-howrows { gap: var(--lp-m4) !important; }
  .lp-howrows > div { padding-block-start: var(--lp-m3) !important; }
}


/* ======================================== #how, the step facts and the ghost

   THE ICONS WERE RENDERING AT 200px SQUARE. `.lp-stepfact`, `.lp-stepfact-i`,
   `.lp-stepfact-t` and `.lp-stepcopy-ghost` are four of the twenty-five classes
   the design's markup uses that arrived with no rule in any sheet -- the export
   shipped the new markup against the previous page's hand sheet. An inline SVG
   with no width and no height is 300x150 by default, so each fact chip's glyph
   filled its own row: a 676px stack of three chips that should be 80px, three
   times over, and the white shape standing where a 16px icon belongs.

   THE CHIP IS A FILL, NOT A RIM. Borderless law: separation comes from the
   plate, never from a hairline around it.

   THE GHOST IS NOT PAINTED, and the rule below says why. */
.lp-stepfacts { align-items: center; }
.lp-stepfact {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 11px;
  border-radius: var(--lp-r-pill);
  background-color: #ffffff0d;
  font-size: 13px;
  line-height: 1.25;
  color: var(--lp-ink-2);
}
.lp-stepfact-i {
  display: grid;
  place-items: center;
  inline-size: 16px;
  block-size: 16px;
  flex: none;
  color: var(--lp-accent-ink);
}
.lp-stepfact-i svg {
  inline-size: 16px;
  block-size: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.lp-stepfact-t { white-space: nowrap; }

.lp-stepcopy { position: relative; }
.lp-stepcopy-ghost {
  /* NOT PAINTED. Drawn as a watermark it read 1.06:1 against the ground and
     site/proof.mjs fails every painted text node under 4.5:1 -- and a numeral
     lifted to 4.5:1 is not a watermark any more, it is a second heading
     competing with the one beside it. The step number is not lost: the
     "Step 01" label directly under this sits in ink that passes, which is
     where a reader was going to read it anyway. */
  display: none;
}


/* ================================================= the guarantee strip, #guard

   THE WHOLE BAND ARRIVED UNSTYLED. `lp-vow3grid`, `lp-vow3`, `lp-vow3-top`,
   `lp-vow3-num`, `lp-vow3-tile`, `lp-vow3-head`, `lp-vow3-say` and `lp-rise`
   are eight more of the classes the design's markup names and no sheet in this
   repo declares, so the three guarantees rendered as a single column of plain
   text under icons at 300x150 -- the browser's default for an inline SVG with
   no size. It measured 3,911px at 1280 and the design gates scored it 1 out of
   1000 against this page's own median band, which is what a third of a page
   carrying nothing scores.

   THREE UP, BREAKING STRAIGHT TO ONE. The page's own comment above the markup
   asks for exactly that and says why: at minmax(200px) three columns never
   pass through a row of two over a widow.

   NO ICON TILE. A glyph in a rounded plate stacked over a heading is the
   generated-page tell the finish checklist names, and the borderless law wants
   the plate gone anyway. The mark is a bare glyph, nothing under it.

   CENTRED, NUMERALS OFF, GLYPH ON TOP AND LARGER, 2026-09-20, his call. The
   ordinals numbered a set that is not a sequence, so they read as steps the
   reader has to take in order; the three promises are simultaneous and always
   true. With the numeral gone the glyph has the line to itself, which is the
   only reason it can be set at 30px without crowding the head beside it, and
   each cell centres on its own column. Law 8 wants a heading block centred in
   its band and this is three of them.

   THE HUE IS THE ACCENT PAIR, reversing the success pair the band was rebuilt
   in on 2026-09-14. The ticks in the listing cards directly above this are
   already --lp-accent-ink, so the strip now answers in the colour the page
   owns rather than in a second one. */
.lp-vow3grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--lp-m5);
}
.lp-vow3 {
  display: grid;
  gap: 9px;
  align-content: start;
  justify-items: center;
  text-align: center;
}
.lp-vow3-top {
  display: flex;
  align-items: center;
  justify-content: center;
}
.lp-vow3-tile {
  display: grid;
  place-items: center;
  inline-size: 30px;
  block-size: 30px;
  flex: none;
  color: var(--lp-accent-ink);
}
.lp-vow3-tile svg {
  inline-size: 30px;
  block-size: 30px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.lp-vow3-head {
  font-size: var(--lp-mt-h3);
  font-weight: 600;
  line-height: 1.18;
  letter-spacing: -0.02em;
  text-wrap: balance;
  color: var(--lp-ink);
}
/* The second half of each promise is the half that names what is refused. */
.lp-vow3-head span { color: var(--lp-accent-ink); }
.lp-vow3-say {
  font-size: var(--lp-mt-small);
  line-height: 1.45;
  color: var(--lp-ink-2);
}


/* ============================================ the hero card title, descenders

   `.lp-card2-title` is a two-line `-webkit-line-clamp` over `overflow: hidden`,
   and the clip box is exactly two line boxes tall. That held while the titles
   were short ("2020 BMW X5 xDrive40i"). The design made them full listing
   lines -- "2020 BMW X5 xDrive40i | 69,117 km | Won't Last Long" -- which fill
   both lines, and a descender on the second one is then cut by the box.
   proof/typeset.mjs check 2 reads the ink, not the layout box, which is why a
   scrollWidth probe calls this clean: the glyph is clipped, not overflowing.

   The pair grows the CLIP box without moving anything under it. */
.lp-card2-title {
  padding-block-end: 0.16em;
  margin-block-end: -0.16em;
}

/* Two lines cannot hold a full listing title on a phone, and the clamp then
   cuts the last glyph rather than ending on one. A third line at the widths
   where the card is narrowest; the desktop card still clamps at two. */
@media (max-width: 480px) {
  .lp-card2-title { -webkit-line-clamp: 3; }
}
/* The lead card is the narrowest of the three on a phone and carries the
   longest title, so three lines still ended on a cut glyph at 360 and 390. */
@media (max-width: 400px) {
  .lp-card2-first .lp-card2-title { -webkit-line-clamp: 4; }
}


/* =========================================================== #how, the panels
   play their own step.                                          2026-09-21

   THE THREE STEP PANELS WERE DRAWINGS. They inherited the row's y/opacity fade
   from `armSectionEntrances` and then held, which is what `gates.mjs
   --ambition` was reading when it measured this page at 0 elements animated at
   rest. The bar for this pass is Raycast's product frames, where the mock UI
   performs the product's own sequence inside the frame -- a query types
   itself, the list resolves under it, the detail pane fills -- so the drawing
   ARGUES for the feature instead of illustrating it.

   EVERYTHING BELOW IS A FINISHED STATE. Every custom property here defaults to
   the value the panel has shipped since 2026-09-06: `--lp-ty: 1` is a whole
   address, `--lp-pick: 1` is the picked row at its full accent fill, and the
   pointer is opacity 0. lot.js sets the start states itself, at arm time, only
   on a panel it has just proved is below the fold, and puts them back in a
   catch. Blocked, refused, reduced or headless, this is the page that was here
   yesterday.

   NO CANVAS. A WebGL layer per panel would be weight spent drawing a thing
   that is pure interface state, and Law 14 will not have a heavy 3D canvas
   under a scroll-triggered page. The whole sequence is GSAP -- already in the
   head for the hero -- moving numbers that this sheet turns into pictures, so
   it costs the page 0KB.

   NOTHING HERE IS PAINTED BY JS. Law 11: every colour below is a var this
   project already declares, mixed against its own token rather than restated
   as a literal. -------------------------------------------------------------- */

/* ---- the address typing itself, frame one -------------------------------
   ONE ELEMENT WIDE, WHICH IS THE WHOLE TRICK. `.lp-pan-type` is `justify-self:
   start` inside the well's grid, so its 100% is the text's own width and not
   the field's. The text is then revealed by a clip-path off `--lp-ty` and the
   caret parked at that same fraction of that same width, which means the caret
   lands on the reveal edge at every container size with nothing measured in
   `ch` and no layout read per frame. `nowrap` holds it to one line: at the
   narrowest the panel ever gets, `.lp-pan-scr` clamps to 9.5px and these 25
   characters are about half the well. */
.lp-pan-type {
  position: relative;
  justify-self: start;
  white-space: nowrap;
  --lp-ty: 1;
  --lp-tc: 0;
}
.lp-pan-type > span {
  display: inline-block;
  /* Negative insets on the two sides the clip does not drive: a right-hand
     inset of 0 still clips the descender of a `y` and the overshoot of a `/`
     against the em box. */
  clip-path: inset(-0.12em calc((1 - var(--lp-ty)) * 100%) -0.16em -0.04em);
}
/* borderless-keep: this is the CARET IN A TEXT FIELD, which is the one thing a
   2px vertical line in a filled well can be. Law 1 bans the rim and keeps the
   line that draws a picture; `.lp-pan-lines i` is already kept on the same
   grounds two rules up in the built sheet. It is opacity 0 except in the
   second and a half the address is being typed, and it is the project's own
   accent because a caret is the one place on this page where "LotPost is
   waiting for you" is literally true. */
.lp-pan-type::after {
  /* The machine-readable half of the keep above. `gates.mjs --borderless`
     reads this property off the pseudo's own computed style; the comment is
     the reason and this line is the declaration, because a comment above a
     rule is how a 1.5px ring carried a "borderless-keep" tag for months. */
  --borderless-keep: 1;
  content: "";
  position: absolute;
  inset-block: 0.04em -0.08em;
  inset-inline-start: calc(var(--lp-ty) * 100%);
  inline-size: 0.1em;
  border-radius: var(--lp-r-pill);
  background: var(--lp-accent);
  opacity: var(--lp-tc);
}

/* ---- the title being written, frame three -------------------------------
   WORD BY WORD, NOT CHARACTER BY CHARACTER, and that is the honest motion for
   this box rather than a second helping of the one above it. Frame one is a
   person typing an address they know; frame three is core/title.mjs handing
   back a line it built. Different actor, different motion. The wrapper spans
   are written by lot.js at arm time and the original text is restored if
   anything in that block throws. */
.lp-pan-words { display: block; }
.lp-pan-w { display: inline-block; }

/* ---- the description filling, frame three -------------------------------
   The four bars grow from their own start edge rather than fading, so the
   block reads as prose being SET rather than as four shapes arriving. */
.lp-pan-lines i { transform-origin: left center; }

/* ---- the picked row, frame two ------------------------------------------
   Both halves of the pick -- the accent fill and the accent ink -- come off
   ONE property, so a row cannot ever be caught half picked. At 1 this computes
   to rgba(242,169,59,0.12), which is --lp-accent-12 exactly: the same fill the
   built sheet paints, restated here only so it has a dial on it. `srgb` and
   not `oklch` on purpose -- a straight alpha ramp on one hue wants no gamut
   trip on the way. */
.lp-pan-row.is-pick {
  background: color-mix(in srgb, var(--lp-accent) calc(var(--lp-pick, 1) * 12%), transparent);
}
.lp-pan-row.is-pick .lp-pan-rn,
.lp-pan-row.is-pick .lp-pan-rp {
  color: color-mix(in srgb, var(--lp-accent-ink) calc(var(--lp-pick, 1) * 100%), var(--lp-ink));
}

/* ---- the pointer ---------------------------------------------------------
   IT SCALES WITH THE DRAWING AND NOT WITH THE PAGE. `.lp-pan` is already an
   inline-size container (that is how the whole panel shrinks as one object),
   so this repeats `.lp-pan-scr`'s own clamp against the same container and the
   arrow is the same size relative to the screen at 320 as it is at 1440. Law
   12's trap is a `vw` or a media query in here; there is neither.

   THE DARK EDGE IS A SHADOW, NOT A RIM. It has to stay legible crossing a
   photograph in frame two, and Law 1 has no exception for an outline on a
   glyph. A drop-shadow with a real offset and a real blur is depth. */
/* AND IT IS PLACED IN PER CENT OF THE PANEL, NOT IN PIXELS. It was a GSAP x/y
   transform in px, measured off the controls at the width the sequence played
   at, and `gates.mjs --widths` caught exactly what that costs: resize the
   window after a panel has finished and the pointer keeps a pixel offset that
   belonged to a wider panel -- 39px past the right edge of the page at 320.
   A percentage is resolved against this panel every time it is laid out, and
   this panel is proportional at every width by construction (every length
   inside it is an `em` off one container-query clamp), so the pointer lands on
   the same control at 320 as at 1440 with nothing recomputed. The two margins
   are the arrow's own tip, which sits about 24% across and 10% down its box.
   THE TIP IS OFFSET, THE TRANSFORM IS LEFT FREE: the resting float at the end
   of frame three is a `translate`, so it never touches this. */
.lp-pan-cur {
  position: absolute;
  inset-inline-start: calc(var(--lp-cx, 50) * 1%);
  inset-block-start: calc(var(--lp-cy, 50) * 1%);
  margin-inline-start: -0.36em;
  margin-block-start: -0.15em;
  z-index: 3;
  font-size: clamp(9.5px, 3.62cqw, 13.6px);
  inline-size: 1.5em;
  block-size: 1.5em;
  color: var(--lp-ink);
  opacity: 0;
  pointer-events: none;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.8));
}
.lp-pan-cur svg {
  display: block;
  inline-size: 100%;
  block-size: 100%;
}


/* ===========================================================================
   THE 2026-09-21 DESIGN ROUND, PORTED.

   What is below is the part of the Claude Design landing round that the repo
   cannot draw on its own: seventeen classes the new markup asks for and no
   sheet here defines. It is a PORT and not the design's sheet: that sheet is
   a fork of an older `lot.css` and re-declares the headline, the lede, the
   button and the section ladder at the sizes they had before this repo
   retuned them, which `site/proof.mjs` reads as the page going backwards.
   Only the round's own additions come across; every rule the repo already
   owns stays the repo's.

   Sections it draws: the section mark, the caps section title, the centred
   step copy with its card and ghost numeral, the FAQ's open/closed treatment,
   the mast's glass state, the arrival animation, and the hero's two-line
   headline split.
   =========================================================================== */

.lp-signin-ic { inline-size: 15px; block-size: 15px; flex: none; opacity: 0.8; }

/* The panel's action row, now the mast's only offer. */
.lp-menu-cta {
  display: flex;
  justify-content: center;
  margin-block-start: var(--lp-m2);
  font-weight: 700;
  color: #1a1103;
  background: linear-gradient(176deg, #f8c465 0%, #f0a82e 52%, #e0951d 100%);
  /* The round lit the top edge with `inset 0 1px 0`. That is a rim (Law 1),
     and the fill already carries the light: the gradient opens at #f8c465. */
  box-shadow: 0 1px 2px #00000099;
}

.lp-menu-cta:hover {
  color: #1a1103;
  background: linear-gradient(176deg, #fbd07f 0%, #f4b241 52%, #e89f22 100%);
}

/* The round set the four step titles in an ink-to-amber wash clipped to the
   glyphs. It is off for the same reason the section heads' wash came off on
   2026-09-12: measured, the amber end of it lands under the contrast floor on
   this ground, and a heading that fades is a heading that is harder to read.
   To revert, restore the four lines this comment replaced. */
.lp-stepcopy-h {
  color: var(--lp-ink);
}

/* ============ THE HEADLINE BREAKS IN TWO, 2026-09-16 (requested). Each phrase
   is two blocks now rather than one run of words finding its own line breaks,
   so all three rotations are the same two-line shape and the deck below them
   never moves as the phrase changes. The split is authored at the phrase's own
   balance point (the accent word closes line one), which is what a soft
   text-wrap:balance could not guarantee across three different sentences. */
.lp-h1-half { display: block; }

/* ================= THE THREE STEPS READ CENTRED, 2026-09-17 (requested).

   The copy column was a left-ragged block beside its panel. It is centred now
   -- kicker, title, sentence and facts on one axis, the panel centred under
   the same axis in its own cell -- so each step reads as one object rather
   than a column of text with a picture next to it. Centring a left-icon fact
   list would have left three ragged rows in the middle of a centred block, so
   the facts become PILLS on a wrapping centred row: same glyph, same accent
   chip, no column edge to break the axis. Three things carry the extra weight,
   and each is a state or a texture no inline style can hold.

   1 THE GHOST NUMERAL sits on the centre line, not the left edge, and its
     outline is a hair brighter so it survives being read behind centred text.
     The mirrored middle row's right-edge override is cancelled here.
   2 A SOFT AMBER GLOW behind the words, out of flow and pointer-transparent,
     so the block has a light source and the section is not three flat bands.
   3 THE TITLE WEARS A GRADIENT RULE under it -- amber fading out both ways,
     which is the only horizontal line left in the section.
   Pills lift and take an accent hairline on hover or focus-within; reduced
   motion keeps the tint and drops the lift. */
.lp-stepcopy-mid .lp-stepcopy-ghost {
  inset-inline-start: 50%;
  inset-inline-end: auto;
  translate: -50% 0;
  -webkit-text-stroke: 1px #ffffff17;
}

.lp-stepcopy-mid::before {
  content: "";
  position: absolute;
  z-index: 0;
  inset-block-start: -16%;
  inset-inline-start: 50%;
  translate: -50% 0;
  /* the 130% is what makes the bloom read as light rather than a disc, and
     on a 360 phone it is also 31px of page the reader can scroll to. The
     viewport is the third bound: the glow still runs past the copy column
     at every width, and never past the page. */
  inline-size: min(620px, 130%, 100vw);
  aspect-ratio: 1.55;
  background: radial-gradient(50% 50% at 50% 50%, #f2a93b1c 0%, #f2a93b00 68%);
  pointer-events: none;
}

/* THE DIVIDER, 2026-09-21 (requested). It was a 68px amber bar: a blunt stub
   under a large title. One element still, three background layers: a wide
   hairline that fades to nothing at both ends, a soft amber bloom behind the
   middle, and a 5px accent diamond on the centre line. It scales with the
   column, so the same rule reads right on a phone and at full width. */
.lp-stepcopy-mid .lp-stepcopy-h::after {
  content: "";
  display: block;
  margin: 18px auto 2px;
  inline-size: min(78%, 210px);
  block-size: 9px;
  background:
    linear-gradient(90deg, #f2a93b00 0%, var(--lp-accent-42) 26%, var(--lp-accent) 50%, var(--lp-accent-42) 74%, #f2a93b00 100%) center / 100% 1px no-repeat,
    radial-gradient(42% 100% at 50% 50%, #f2a93b2e 0%, #f2a93b00 70%) center / 100% 9px no-repeat,
    linear-gradient(var(--lp-accent), var(--lp-accent)) center / 5px 5px no-repeat;
}

.lp-stepcopy-mid .lp-stepfact {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 7px 14px 7px 8px;
  border-radius: 999px;
  background: #ffffff06;
  
  transition: background 200ms var(--lp-m-ease), box-shadow 200ms var(--lp-m-ease), translate 200ms var(--lp-m-ease);
}

.lp-stepcopy-mid .lp-stepfact:hover,
.lp-stepcopy-mid .lp-stepfact:focus-within {
  background: #ffffff0f;
  
  translate: 0 -2px;
}

.lp-stepcopy-mid .lp-stepfact-i {
  inline-size: 24px;
  block-size: 24px;
  border-radius: 8px;
}

.lp-stepcopy-mid .lp-stepfact-i svg { inline-size: 14px; block-size: 14px; }

.lp-stepcopy-mid .lp-stepfact-t {
  gap: 0;
  padding-block-start: 0;
  text-align: start;
}

/* ============================================ GLASS OVERLAY ON THE HERO, 2026-09-21

   Siavash: "add glass overlay on hero banner effect". The plate is back, but as
   glass rather than the old black slab: it takes its colour from the hero photo
   behind it (blur + saturate on the backdrop) instead of covering it, with one
   hairline rim and a top-edge highlight so the sheet reads as a pane of glass.
   Height, gutter and ink are unchanged, so nothing below the bar moves. */
.lp-mast .lp-mast-in.lp-mast-glass {
  position: relative;
  background: linear-gradient(to bottom, #ffffff1f, #ffffff0a 42%, #ffffff05);
  -webkit-backdrop-filter: blur(20px) saturate(1.6);
          backdrop-filter: blur(20px) saturate(1.6);
  border-radius: 22px;
  padding-inline: clamp(14px, 2vw, 22px);
  box-shadow: 0 18px 40px -24px #000000b3;
}

/* THE RULE UNDER THE STEP TITLES IS GONE, 2026-09-21. Siavash: the hairline
   above the title is the one that stays; with the title back in its card the
   second rule under it was a third horizontal line in eight lines of copy. */
.lp-stepcopy-mid .lp-stepcopy-h::after { content: none; }

/* ================================= THE TITLE CARDS ARE ONE SIZE, 2026-09-21

   Siavash: "make sure all the cards are the same size and the title should be
   inside of it". They hugged their text, so four cards came out four widths
   and the short titles sat in stubs. The card now takes the copy column's full
   measure and holds a floor height, with the title centred inside it. */
/* THE CARD IS A LAYER BEHIND THE TITLE, NOT A FILL ON IT, 2026-09-21. The
   head paints its own gradient through background-clip: text, so any fill set
   on the element itself replaces that gradient and the words disappear. The
   card is drawn by ::before instead, one layer back. */
.lp-stepcopy-mid .lp-stepcard {
  display: grid;
  align-content: center;
  inline-size: 100%;
  min-block-size: 5.2rem;
  box-sizing: border-box;
  padding: 14px 24px 16px;
  isolation: isolate;
}

/* THE TITLE SITS LIKE TYPE, NOT LIKE A LABEL, 2026-09-21. On the plate the
   head can afford tighter tracking and a real optical size: it is the only
   thing in the box, so the leading closes up and the words balance across
   their lines rather than breaking wherever the column ends. */
.lp-stepcopy-mid .lp-stepcard {
  font-size: clamp(1.85rem, 3vw, 2.5rem);
  line-height: 1.02;
  letter-spacing: -0.04em;
  text-wrap: balance;
  font-feature-settings: "kern" 1, "liga" 1, "calt" 1;
  text-rendering: optimizeLegibility;
  padding-block: 16px 18px;
}

/* THE PLATE SPEAKS THE PAGE'S CARD LANGUAGE, 2026-09-21. Siavash: "you can do
   better, this looks ugly". The first pass was a flat #ffffff0a rectangle with
   a grey rim, which is the one surface treatment nothing else on this page
   uses. It now carries the same three layers every stage and panel here does:
   a raking white sheen off the top-left, an amber bloom in the same corner,
   the surface tone under both, one hairline rim and a lifted shadow. */
.lp-stepcopy-mid .lp-stepcard::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: 20px;
  background-image:
    linear-gradient(155deg, #ffffff1a 0%, #ffffff08 38%, transparent 64%),
    radial-gradient(120% 130% at 6% 0%, var(--lp-accent-12) 0%, transparent 58%);
  background-color: var(--lp-surface-2);
  box-shadow: 0 24px 50px -32px #000000a6;
  pointer-events: none;
}

/* ==================================== THE SECTION MARK, 2026-09-21

   Siavash: "replace this ugly divider, add something better and different,
   unique artistic style". Every section head opened on the same 28x2 amber
   stub, which is the most generic mark a page can wear. In its place: a
   struck diamond with two strokes running off it at different lengths and
   weights, so the mark has a direction and a rhythm instead of being a dash.
   Pure CSS on the same element, no new markup. */
.lp-secmark {
  position: relative;
  display: block;
  inline-size: 46px;
  block-size: 13px;
  margin-block-end: 4px;
  background-image:
    linear-gradient(var(--lp-accent), var(--lp-accent)),
    linear-gradient(90deg, var(--lp-accent-42), #f2a93b00);
  background-repeat: no-repeat;
  background-size: 22px 2px, 34px 1px;
  background-position: 12px 3px, 12px 9px;
}

.lp-secmark::before {
  content: "";
  position: absolute;
  inset-block-start: 1px;
  inset-inline-start: 0;
  inline-size: 7px;
  block-size: 7px;
  background: var(--lp-accent);
  rotate: 45deg;
}

.lp-secmark::after {
  content: "";
  position: absolute;
  inset-block-start: 7px;
  inset-inline-start: 5px;
  inline-size: 4px;
  block-size: 4px;
  background: var(--lp-accent-42);
  rotate: 45deg;
}

/* ===== THE GHOST NUMERAL GETS ITS OWN BAND, 2026-09-21 (requested). It was
   pulled up by a negative em off the first line, which only works while the
   first line is small type: with the title on a plate the 150px outline came
   down across the card and read as a rendering fault. The column now reserves
   a top band the numeral lives inside -- so nothing is positioned over the
   title -- and the block gets breathing room on both sides. */
.lp-stepcopy-mid {
  padding-block-start: clamp(6px, 1vw, 14px);
  padding-inline: clamp(10px, 2vw, 22px);
  padding-block-end: clamp(6px, 1vw, 14px);
  box-sizing: border-box;
}

.lp-stepcopy-mid .lp-stepcopy-ghost {
  inset-block-start: 0;
  font-size: clamp(58px, 7vw, 100px);
  line-height: 0.86;
}

/* ===== THE PLATE HUGS THE TITLE, 2026-09-21 (requested). It was set to the
   column's full measure with a floor height, so the card was a band across the
   column with the words floating in the middle of it. It is now sized by the
   title: the plate ends where the longest line ends, on both axes, and the
   floor height goes with it. The title keeps its balanced wrap, so a two-line
   title makes a two-line plate rather than stretching to the column edge. */
.lp-stepcopy-mid .lp-stepcard {
  inline-size: fit-content;
  max-inline-size: 100%;
  min-block-size: 0;
  padding: 12px 20px 14px;
}

/* ===== THE TITLE PLATE IS GONE, 2026-09-21 (requested): "restore to when
   there wasn't a card background". The plate, its rim, its bloom and its
   shadow are dropped and the wrapper goes back to being nothing but the box
   the title sits in. The title's own type treatment (its size, its tighter
   tracking and its balanced wrap) stays, because that was never the card. */
.lp-stepcopy-mid .lp-stepcard {
  inline-size: auto;
  min-block-size: 0;
  padding: 0;
  isolation: auto;
}

.lp-stepcopy-mid .lp-stepcard::before { display: none; }

/* ===== THE QUESTIONS LEVELLED UP, 2026-09-21 (requested). Seven cards that
   were a padded fill with a hover lift now carry the states a disclosure
   actually has: the number is a tile that FILLS with the accent when its
   answer is open (accent-on ink on it, never the accent as text), the chevron
   turns and lights, a 2px accent edge runs down the open card, and the answer
   itself arrives rather than appearing. The answer is indented to the question
   text's own column so the two read as one block.

   IT IS A CLASS AND NOT INLINE for the only reason a class is ever earned
   here: `[open]`, `:hover`, `::before` and keyframes cannot be written in a
   style attribute. The inline styles the cards carried for the resting fill
   came out with it, so one place owns the card. */
.lp-q-lux {
  position: relative;
  overflow: hidden;
  padding: 16px var(--lp-m5);
  border-radius: var(--lp-r-frame, 22px);
  background-color: var(--lp-surface);
  background-image: linear-gradient(180deg, #ffffff0d 0%, transparent 46%);
  
  transition: translate .3s cubic-bezier(.2, .7, .2, 1),
              background-color .3s ease,
              box-shadow .3s ease;
}

.lp-q-lux:hover {
  translate: 0 -2px;
  background-color: var(--lp-surface-3);
  box-shadow: 0 18px 34px -26px #000000cc;
}

.lp-q-lux[open] {
  background-color: var(--lp-surface-3);
  box-shadow: 0 18px 40px -28px #000000cc;
}

/* The round marked the open card with a 2px amber rail down its leading edge.
   The four rails on this page came off on 2026-09-12 for the same reason: a
   hairline on a container edge reads as a rim (Law 1), and seven of them in
   two columns read as a striped list. Open is carried by the fill, the lift,
   the amber index chip and the chevron turning. */

.lp-q-lux > summary {
  display: grid;
  /* THREE children, not two. The round's summary was index-free, so a two
     column track was right for it; the seven cards here still carry the
     numbered chip the built sheet introduced, and with two tracks the
     QUESTION landed in the 22px chevron column and set itself 22px wide and
     130px tall while the chevron wrapped to a second row. Number, question,
     chevron. */
  /* The chevron track is `auto`, not 22px: the built sheet gives the glyph a
     7px disc, so it measures 36px and a fixed 22px track put 14px of it past
     the card's inline padding. */
  grid-template-columns: auto minmax(0, 1fr) auto;
  /* The frame owns the padding now: `.lp-q summary` and `.lp-q p` in the
     built sheet were written for a bare <details>, so inside `.lp-q-lux`,
     which pads itself, they doubled to 32px over every question and 48px
     under every open answer. The 4px hang that puts the answer under the
     question's first letter rather than under the number is kept. */
  padding: 0;
  align-items: center;
  gap: 14px;
  min-block-size: 44px;
  cursor: pointer;
  list-style: none;
  font-weight: 600;
  font-size: 16px;
  line-height: 1.35;
  color: var(--lp-ink);
  text-wrap: pretty;
}

.lp-q-lux > summary::-webkit-details-marker { display: none; }

.lp-q-lux .lp-q-n {
  display: grid;
  place-items: center;
  inline-size: 34px;
  block-size: 34px;
  border-radius: 11px;
  font: 600 12px/1 var(--lp-face-mono);
  letter-spacing: .04em;
  color: var(--lp-accent-ink);
  background-color: var(--lp-accent-12);
  
  transition: background-color .3s ease, color .3s ease, box-shadow .3s ease;
}

.lp-q-lux[open] .lp-q-n {
  background-color: var(--lp-accent);
  color: var(--lp-accent-on);
  box-shadow: 0 10px 22px -12px rgba(242, 169, 59, .75);
}

.lp-q-lux > summary > svg {
  inline-size: 22px;
  block-size: 22px;
  color: var(--lp-muted);
  transition: rotate .3s cubic-bezier(.2, .7, .2, 1), color .3s ease;
}

.lp-q-lux[open] > summary > svg {
  rotate: 180deg;
  color: var(--lp-accent-ink);
}

.lp-q-lux > p {
  margin: 12px 0 0;
  padding: 2px 0 0 4px;
  color: var(--lp-ink-2);
  font-size: 15px;
  line-height: 1.6;
  text-wrap: pretty;
}

.lp-q-lux[open] > p {
}

/* ===== THE #how TITLE IS SET IN CAPS AND IT ARRIVES, 2026-09-21 (requested).
   Caps at a section title's size need the tracking a lowercase setting does
   not: the resting frame is 0.13em, and the entrance OPENS from 0.32em, so the
   two words unpack outward from their own centre instead of sliding. Three
   background layers, top to bottom: a sheen that crosses once, the centred
   bloom the head already had, and the symmetrical ink-to-amber wash. The sheen
   is the only layer that moves, which is why the position keyframes restate
   the other two unchanged.

   IT LIVES HERE AND NOT INLINE because keyframes, a multi-layer
   background-size and a scroll timeline cannot be written in a style
   attribute. The selector carries the section chain from the `.lp-in` arrival
   rule above plus the modifier, so it outranks that rule's `animation`
   shorthand rather than being silently replaced by it. */
/* The `#main` prefix is NOT decoration: the sheet's own `#main .lp-sec .lp-h2`
   rule carries an ID and would otherwise keep both the negative lowercase
   tracking and the generic silver gradient under the caps. */
#main .lp-in > .lp-wrap > * > .lp-h2.lp-h2-caps,
#main .lp-h2.lp-h2-caps {
  text-transform: uppercase;
  letter-spacing: 0.13em;
  font-weight: 700;
  line-height: 1.08;
  background-image:
    linear-gradient(104deg, #ffffff00 0%, #fffffff2 50%, #ffffff00 100%),
    radial-gradient(70% 180% at 50% 130%, color-mix(in oklch, var(--lp-accent) 45%, #fff) 0%, transparent 46%),
    linear-gradient(90deg, var(--lp-accent-ink) 0%, color-mix(in oklch, var(--lp-ink) 45%, var(--lp-accent-ink)) 16%, var(--lp-ink) 38%, var(--lp-ink) 62%, color-mix(in oklch, var(--lp-ink) 45%, var(--lp-accent-ink)) 84%, var(--lp-accent-ink) 100%);
  background-size: 55% 100%, 100% 100%, 100% 100%;
  background-position: 160% 0, 0 0, 0 0;
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  padding-block-end: 0.08em;
  margin-block-end: -0.08em;
}


@keyframes lp-q-answer {
  from { opacity: 0; translate: 0 -7px; }
  to   { opacity: 1; translate: none; }
}

@keyframes lp-h2caps-open {
  from { opacity: 0; letter-spacing: 0.32em; translate: 0 16px; filter: blur(7px); }
  to   { opacity: 1; letter-spacing: 0.13em; translate: none; filter: blur(0); }
}

@keyframes lp-h2caps-sheen {
  from { background-position: -60% 0, 0 0, 0 0; }
  to   { background-position: 160% 0, 0 0, 0 0; }
}

@media (prefers-reduced-motion: reduce) {
  .lp-who-mk-a, .lp-who-mk-b, .lp-who-mk-c { animation: none; opacity: 1; translate: 0 0; }
}

@media (prefers-reduced-motion: reduce) {
  .lp-stepcopy-mid .lp-stepfact:hover,
  .lp-stepcopy-mid .lp-stepfact:focus-within { translate: none; }
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .lp-mast .lp-mast-in.lp-mast-glass { background: #0a0c10d9; }
}

@media (prefers-reduced-motion: reduce) {
  .lp-q-lux,
  .lp-q-lux > summary > svg { transition: none; }
  .lp-q-lux:hover { translate: none; }
  .lp-q-lux[open] > p { animation: none; }
}

@supports (animation-timeline: view()) {
  #main .lp-in > .lp-wrap > * > .lp-h2.lp-h2-caps {
    animation-timeline: view(), view();
    animation-delay: 0s, 0s;
    animation-range: entry 4% cover 30%, entry 10% cover 46%;
  }
}

@media (prefers-reduced-motion: reduce) {
  #main .lp-in > .lp-wrap > * > .lp-h2.lp-h2-caps {
    animation: none;
  }
}

@media (forced-colors: active) {
  #main .lp-in > .lp-wrap > * > .lp-h2.lp-h2-caps,
  #main .lp-h2.lp-h2-caps {
    background-image: none;
    color: CanvasText;
    -webkit-text-fill-color: CanvasText;
    animation: none;
  }
}


/* ===== THE STEP FRAME'S BACKDROP, 2026-09-21. The design round wrote this
   layer as a `style-before` attribute on each frame. No browser reads that
   attribute: it is the design runtime's way of writing a pseudo-element from
   the markup, so the blurred lot photograph behind all four step frames was
   never painting here. A ::before cannot be written inline, which is the one
   case this sheet exists for. The photograph stays on the element, as
   `--lp-stepfx`, so each frame still names its own picture and nothing here
   has to know how many steps there are. */
[data-stepfx]::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background-image: var(--lp-stepfx);
  background-size: cover;
  background-position: center;
  filter: blur(22px) brightness(0.28) saturate(0.75);
  opacity: 0.85;
  z-index: 0;
}


/* ===== NO GRADIENT TEXT, 2026-09-21. The round set the section titles in a
   clipped background: `.lp-h2-caps` on #how, and an inline wash on the other
   eight, which the markup no longer carries. The house ban on
   `background-clip: text` is flat, and this repo had already reversed the
   same wash once on measured contrast, which is what the `.lp-sec .lp-h2`
   rule above is. The caps treatment keeps everything that is not the clip:
   the uppercase, the tracking, the weight and the entrance. The ink is the
   one token the h1 is set in. The sheen keyframe stays defined and unused
   rather than deleted, so putting the clip back is one rule. */
#main .lp-in > .lp-wrap > * > .lp-h2.lp-h2-caps,
#main .lp-h2.lp-h2-caps {
  background-image: none;
  -webkit-background-clip: border-box;
  background-clip: border-box;
  color: var(--lp-ink);
  -webkit-text-fill-color: var(--lp-ink);
}




/* ===== REDUCE MEANS STILL, 2026-09-21. The round's own hover and open
   transitions are 200-300ms and its reduce guards covered the animations only,
   so `site/proof.mjs` still read 0.2s of transition on a page that asked for
   none. The states themselves are unchanged; only the travel between them is. */
@media (prefers-reduced-motion: reduce) {
  .lp-stepcopy-mid .lp-stepfact,
  .lp-stepcopy-mid .lp-stepcard,
  .lp-secmark,
  .lp-menu-cta,
  .lp-signin-ic,
  .lp-q-lux,
  .lp-q-lux > summary > svg,
  .lp-q-lux .lp-q-n,
  .lp-q-lux > p,
  .lp-mast .lp-mast-in.lp-mast-glass {
    transition: none;
  }
}


/* ===== THE STEP ROW'S TRACKS CAN SHRINK, 2026-09-21. A grid item will not go
   under its own automatic minimum, so at 320 the round's two-up step row held
   its children at 305px inside a 284px column and the page grew 11px it could
   be scrolled to. `min-inline-size: 0` is the house answer to exactly this
   (the rule the panel frame and the copy column both needed), and it changes
   nothing at 360 and up, where the column was already wider than the content. */
.lp-howrows > div > * {
  min-inline-size: 0;
}

/* THE BACKGROUND PICKER CARRIES SIX FRAMES, NOT FIVE. `.lp-pan-strip` in the
   built sheet is a five-track grid, and the round's picker shows six, so the
   sixth dropped to a row of its own under a full line. One track per frame. */
.lp-pan-strip-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
