/* ==========================================================================
   web/src/styles/page.css

   The secondary-page shell: the one frame every page that is not the landing page wears, and the
   only file that owns it. Four things and nothing else: the page frame's keylines and its
   vertical ladder, the page masthead, the reading column, and the two grouping steps a page
   builder spaces content with. It carries nothing about any individual page: a page's own rules
   live in web/src/styles/pages/<name>.css, which the build loads for that page alone, so seven
   page builders can work at once without ever editing this file.

   WHY IT IS NOT sheet.css. sheet.css and body.css are the landing page's own design, THE SHEET.
   A secondary page must not change shape on the day the landing page does, so it loads neither
   (web/src/styles/README.md, "The five stylesheets"). What it does carry across is the landing
   page's masthead treatment and its ladder, restated here on the frame's own class names rather
   than borrowed from the landing page's.

   THE LADDER, ONE FOR THE WHOLE SITE (founder call, 2026-09-04, Pin, in the founder-nudge thread
   1788329584.269439, read there first-hand; web/DECISIONS.md D109: "Do a information architecture
   pass on the page. Make sure the vertical spacing groups how hierchy of information are grouped
   together visually", and D110: "Make sure that doesn't kill the rhythm you establish on the page.
   Clarity and rhythm should help reinforcing each other"). Every gap on a secondary page is one of
   these, desktop first and phone second, and nothing else:

     8            inside one thing
     24 / 16      within a group
     48 / 32      between groups
     96 / 64      between sections, and the one rest at the foot of the page

   Every number is a whole multiple of the 8 grid and every one is a token, so the ladder moves
   when the grid moves and no coordinate is set by eye (visual-rhythm rule 1).

   THE LARGEST GAP IS THE FOOT OF THE FRAME, and it is deliberate rather than left over
   (visual-rhythm rule 5): a scrolled page's rest has no edge of its own, so it has to be bounded
   by something, and here it is bounded by the footer's dark ink directly beneath it. It is the
   page's one genuinely empty region, unequal on purpose against the dense region above it
   (rule 6). Every other gap on the page is smaller than it, at both widths, measured.

   Loaded by: web/scripts/build-site.mjs, into every page under web/src/pages/, and by
   web/scripts/build-legal-pages.mjs, into all five generated policy pages. No page links it by
   hand.

   Connected files:
     - web/src/styles/tokens.css        (every value spent here)
     - web/src/styles/base.css          (the reset and the self hosted faces)
     - web/src/styles/components.css    (.wrap, the header, the footer, the button, .prose)
     - web/src/styles/pages/            (the per-page slot; one file per page, loaded for it alone)
     - web/src/partials/page-head.html  (the head every secondary page includes)
     - web/scripts/build-site.mjs       (injects this file and the per-page slot)
     - web/scripts/build-legal-pages.mjs (renders the same frame for the policy pages)
     - web/src/pages/404.html           (the worked example of the frame)
     - web/src/styles/README.md         (where this file sits in the load order)
   ========================================================================== */

/* ==========================================================================
   1. The frame.

   .wrap already owns the keylines: --width-page wide, centred, --page-margin on both edges, the
   same left keyline the header and the footer stand on at every width. This class adds only the
   vertical ladder, so the two are always written together: <div class="wrap page-frame">.

   No padding-top: the masthead's own row opens with one grid step above the descriptor, which is
   the landing page's arrangement exactly (sheet.css, .plate__masthead).
   ========================================================================== */

.page-frame {
  /* THE REST AT THE FOOT OF THE PAGE IS 96 DESKTOP AND 64 PHONE, the between-sections rung, and it
     is measured on the render rather than declared here in full: the site footer already carries
     48 of it in its own margin-top, on every page including the landing page, so the frame spends
     the remainder and no more. A frame that spent the whole rung would render 144, which is on the
     8 grid but is not a rung of the ladder, and a gap that is the sum of two separate decisions is
     the passive space visual-rhythm rule 5 refuses. Measured at 1280 and 390. */
  padding-bottom: calc(var(--space-xl) * 2);   /* 80, and the footer's own 48 makes the 128 */
}

/* ==========================================================================
   2. The page masthead.

   The landing page's masthead, restated for a page whose subject is a title rather than an
   object: a descriptor on the left keyline, an optional note on the right, each drawing its own
   rule, and the page's title one group-step below them.

   EACH HALF DRAWS ITS OWN RULE, SIZED TO ITS OWN TEXT, NEVER ONE LINE SHARED ACROSS THE ROW
   (founder call, 2026-09-04, Pin, in the founder-nudge thread 1788329584.269439 at 1788496361,
   read there first-hand: "Make sure the line under 'voice based dating app' runs the full length
   of the text"). Each <p> in the row is a flex item with no flex-grow, so its box is already the
   width of its own words; left: 0 and right: 0 on the pseudo-element below therefore size the
   rule to exactly those words, on every line the row can wrap into. The rule is absolutely
   positioned so it costs the row no height of its own, and the row keeps a transparent
   border-bottom so its total box height does not move by the 1px the visible line would take.
   That is the same arrangement as sheet.css's .plate__masthead, and it is here rather than shared
   with it because sheet.css is the landing page's own file and this page never loads it.

   The row is the one deliberate break on an otherwise regular field (visual-rhythm rule 2): every
   other horizontal edge on a secondary page, the header's and the footer's, runs the full width of
   the frame, and this one stops where its own words stop. One property, extent, in one place.
   ========================================================================== */

.page-masthead__row {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-sm);
  /* THE GAP FROM THE SITE HEADER TO THE SLUG WAS 16 AT BOTH WIDTHS, and 16 is the phone's
     within-a-group rung, not a desktop one (web/DESIGN.md 5.2: 8 / 24 / 48 / 96 / 192 desktop, 8 /
     16 / 32 / 64 / 128 phone). Measured on the render before this change, at safety.html:
     header-bottom to slug-top was 16.00px at 1280 and 16.00px at 390 — the same number carrying
     "site chrome to page" on desktop and "a thing and what serves it" on phone. This is also the
     gap the founder asked more of on 2026-09-03 for the landing page's own masthead ("The line
     'voice first dating app' occupies is too close to the line above. Needs more space",
     sheet.css:196-198), so it moves UP here too: 24 (var(--space-md)) at desktop, 16
     (var(--space-sm), unchanged) at phone, in section 4 below. */
  padding-block: var(--space-sm) var(--space-xs);
  border-bottom: 1px solid transparent;
}

/* L4 of the site's six type levels, the slug: the descriptor's own register, told apart from the
   title below it by face, case, tracking and ink as well as by size, so no two adjacent levels
   are separated by size alone (visual-rhythm rule 3). */
.page-masthead__slug {
  position: relative;
  font-family: var(--font-text);
  font-weight: var(--weight-h3);
  font-size: var(--size-h3);
  line-height: var(--line-h3);
  letter-spacing: var(--track-slug);
  text-transform: uppercase;
  color: var(--hotpot-text-secondary);
}

/* L6, the note: the same register one step quieter, for the apparatus a page carries in its top
   right corner. A page with nothing to say there leaves the element out. */
.page-masthead__note {
  position: relative;
  font-family: var(--font-text);
  font-weight: var(--weight-body);
  font-size: var(--size-body-small);
  line-height: var(--line-body);
  letter-spacing: var(--track-slug);
  text-transform: uppercase;
  color: var(--hotpot-text-secondary);
}

.page-masthead__slug::after,
.page-masthead__note::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  /* 2 below the text, the same as the landing page's masthead (founder call, 2026-09-08, Pin, ts
     1788870035: "C 2 below the text", asked for "consistently apply to other pages too" at ts
     1788866481; web/DECISIONS.md D140, D143). Was --space-xs (8). The named exception to
     web/DESIGN.md 5.4 rule 1; sheet.css .plate__masthead .t-slug::after carries the full note. */
  bottom: calc(-1 * (2px + 1px));
  height: 1px;
  background: var(--hotpot-hairline);
}

/* A 1px background is repainted as the system canvas in forced colours and the rule disappears
   with it, which is the footgun web/CLAUDE.md section 6 names for shadows and frames. CanvasText
   is a system keyword rather than a value this site owns, so it states no colour of its own. */
@media (forced-colors: active) {
  .page-masthead__slug::after,
  .page-masthead__note::after {
    background: CanvasText;
    forced-color-adjust: none;
  }
}

/* L1's face at the H1 role's size. NOT the 64px sheet line: that size belongs to the landing
   page's one display voice, and a second page carrying a second one is the pattern matching
   visual-rhythm rule 9 rules out, one level up (the skill's "The first screen as the measure").
   The descriptor and the title are one group, so the step between them is the group step.

   The bare h1 in the second selector is the generated policy pages' case: the title there is the
   document's own <h1>, lifted out of the rendered markdown and placed here unchanged, anchor id and
   all, because the copy deck is explicit that a policy page's heading comes from the document and
   that the site must not give a document a second name. It carries no class of its own, and adding
   one to it would be this site editing a legal document's markup. */
.page-masthead__title,
.page-masthead > h1 {
  margin-top: var(--space-sm);        /* 16, a thing and what serves it */
  font-family: var(--font-display);
  font-weight: var(--weight-h1);
  font-size: var(--size-h1);
  line-height: var(--line-h1);
  letter-spacing: var(--track-sheet);
  color: var(--hotpot-text-primary);
  max-width: var(--width-measure);
}

/* ==========================================================================
   3. The reading column, and the composition every secondary page wears.

   The measure web/DESIGN.md sets for prose, --width-measure, hung on the frame's own left
   keyline rather than centred in it. Left, because the masthead above it is left and a reading
   column that changes axis halfway down the page has no axis; and because a centred prose column
   running the full height is the first tell in the corporate-website test (visual-rhythm rule 8).

   THE COMPOSITION (2026-09-09). Pin asked whether the composition built for How it works could
   become a system for every page other than the landing page and How it works, in the founder
   thread 1788968944.470079 at ts 1788970647.303479, read there first-hand: "for the spacing, can
   option C be developed into a design system that can also be successfully applied to all other
   pages other than the landing page and how it works?". This section is that system, and
   web/design-proposals/2026-09-09-secondary-page-system.md is its rule text, written for his word
   before web/DESIGN.md section 6 is changed.

   A page is a masthead block, an opening where it has one, a run of groups, and a close where it
   has one. A group is a name, its first sentence one level up, and its body. What the ladder
   spends, desktop first and phone second:

     8   | 8     two lines of one register, and a heading and its own first line
     16  | 16    a thing and what serves it: the first sentence to the body, a line to the list,
                 a form, a control row
     64  | 48    one group to the next
     96  | 64    between sections: before a footnote group, and the page's foot into the footer
     128 | 96    the one rest, before the close, once

   AN OPENING BELONGS TO THE TITLE'S OWN BLOCK (founder call, 2026-09-09, Pin, same thread at ts
   1788981643.218029, read first-hand: "write to {email} should be place just below support wihtou
   the massve gap. they are in a group. same for the two sentences below delete your account"). The
   page's title and the line that opens under it are one block: the title is the heading and the
   opening is the line that serves it, so they sit at the served-line step, 16 at both widths, and
   the first group follows at the group step. Where a page opens straight onto a group, the column
   keeps the group step from the masthead.

   AN OPENING INTRODUCES THE GROUPS BENEATH IT (founder call, 2026-09-09, Pin, thread
   1788968944.470079 at ts 1788979346.549949, read first-hand: "the support page option d looks
   awful, the spacing between support, write to {email} and what to include is huge. wtf?
   information architecture point of view makes no sense. same for delte account"). An opening is
   the line that introduces the groups beneath it, not a section standing on its own, so the gap
   under it is the group step and never a section boundary. That is the whole of what he was
   looking at on Support, where one sentence sat alone with 128 above the first group.

   OPTION D, CONTRAST BY GAP (2026-09-09). The founder read the built system and said the two kinds
   of gap could not be told apart: "the spacing between the section and the the spacing between
   elements withing the section are not visually distinguishable", naming his example as the gap
   between two group headings against the gap between two sentences inside one group (thread
   1788968944.470079, ts 1788976285.076849 and 1788976551.582159, read first-hand). Measured, he was
   right: a group boundary was 48 against a within-group gap of 24, two to one at both widths. The
   research says a gap does the job a drawn box would do and that the ratio is what carries it; the
   one worked example found gives three to one, 8 inside against 24 between. So the within-group
   step comes down to 16 and the group boundary goes up to 64 on the desktop and 48 on the phone,
   which is four to one and three to one. Nothing is invented: every value is still a rung of the
   same 8 grid and still a token.

   THE REST CAME DOWN WITH IT, from 192 to 128 and from 128 to 96: "also the space between call 999
   and the full rules are is also massive" (same message). It is now the size of a section boundary
   and stays the page's largest gap only because no other section boundary falls inside a body.

   THIS SUPERSEDED THE TWO GROUPING STEPS. Until this change the column gave every sibling 24 and
   every group boundary 48, and nothing else existed. That put four different relations on one
   number, which is what the founder read on How it works: "the spacing between sentences and
   sections are almost identical" (Pin, 2026-09-09, in chat). No page sets a gap of its own; a
   page's own file holds its type and its one break.
   ========================================================================== */

.page-column {
  max-width: var(--width-measure);
  margin-top: calc(var(--space-lg) * 2);   /* 64, the masthead is one group, the content the next */
}

/* A page that opens on a line rather than on a group: the title and that line are one block, so the
   column joins the masthead at the served-line step instead of the group step. Same at both widths,
   because the step below the 8 is shared. */
.page-column--opens {
  margin-top: var(--space-sm);             /* 16, the title and the line that serves it */
}

/* Two lines of one register. The default inside a column and inside a group alike, which is what
   makes a group read as one object rather than as a list of equal paragraphs. */
.page-column > * + *,
.page-group > * + *,
.page-open > * + *,
.page-close > * + * {
  margin-top: var(--space-xs);    /* 8 */
}

/* A thing and what serves it. A list, a definition list, a form or a control row answers the line
   above it, so it takes the wider step; the line that follows one is the next line of the same
   body and keeps the 8 above. */
.page-column > * + ul,
.page-column > * + ol,
.page-column > * + dl,
.page-column > * + form,
.page-column > * + .page-actions,
.page-group > * + ul,
.page-group > * + ol,
.page-group > * + dl,
.page-group > * + form,
.page-group > * + .page-actions {
  margin-top: var(--space-sm);    /* 16 */
}

/* A group's first sentence and the body it serves. Stated after the block rule above so a list
   directly under a lede reads the same 16 either way. */
.page-column > .page-lede + *,
.page-group > .page-lede + * {
  margin-top: var(--space-sm);    /* 16 */
}

/* A heading and its own first line, whatever that line is. The narrowest relation on the page and
   the one that makes a name belong to what follows it, so it wins over the served-block step. */
.page-column > h2 + *,
.page-group > h2 + * {
  margin-top: var(--space-xs);    /* 8 */
}

.page-column > .page-group + .page-group,
.page-column > .page-open + .page-open,
.page-column > .page-group + .page-open {
  margin-top: calc(var(--space-lg) * 2);   /* 64, between groups, four times the step inside one */
}

/* An opening introduces the groups beneath it, so it takes the group step, not a section
   boundary. */
.page-column > .page-open + .page-group {
  margin-top: calc(var(--space-lg) * 2);   /* 64, between groups */
}

/* Between sections, spent where a real section boundary falls: before a footnote group, whose
   content is apparatus rather than more of what the page is saying. */
.page-column > .page-group + .page-footnote,
.page-column > .page-open + .page-footnote {
  margin-top: calc(var(--space-xxl) * 2);   /* 96 */
}

/* THE ONE REST, spent once and only where a close stands under it to bound it (visual-rhythm
   rule 5: on a scrolled page a rest has no edge of its own). The close's own ink bounds it, and
   the footer's bounds that. */
.page-column > .page-group + .page-close,
.page-column > .page-open + .page-close {
  margin-top: calc(var(--space-lg) * 4);   /* 128, the one rest, down from 192 */
}

/* ==========================================================================
   3a. The three levels a group is built from, and the two quiet registers.

   No new size token: the opening line and a group's first sentence take the H3 role's size in the
   reading face at the strong weight, which is one level above body and below the section heading
   the display face carries (web/DESIGN.md 5.3). A level bought with face and weight as well as
   size, which is what rule 3 requires of two levels this close together.
   ========================================================================== */

.page-open__line,
.page-lede {
  font-family: var(--font-text);
  font-size: var(--size-h3);
  line-height: var(--line-h3);
  font-weight: var(--weight-strong);
}

/* Both halves of the opening sit inside ONE paragraph, so the element's own text is still the copy
   deck's row byte for byte and no word moves; the blocks exist only so the 8 can sit between them. */
.page-open__line,
.page-open__sub {
  display: block;
}

.page-open__sub {
  margin-top: var(--space-xs);    /* 8, a heading and its own line */
  font-size: var(--size-body);
  line-height: var(--line-body);
}

/* A quiet note: the small body role in the secondary ink, sentence case in the reading face. Not
   the masthead's register, which is uppercase and tracked, because a note is a sentence and the
   masthead's slug is a label. */
.page-note {
  font-size: var(--size-body-small);
  color: var(--hotpot-text-secondary);
}

/* A FOOTNOTE GROUP (founder call, 2026-09-09, Pin, thread 1788968944.470079 at ts 1788976369.765099,
   read first-hand: "pus the whole what this page does not claim as small fonts because they are like
   a foot note. also make sure the system is able to accomadate that"). A group whose content is a
   caveat, a limit, a registration or a reference rather than something the page is telling you takes
   the small size and the secondary ink for its name and its body alike. Nothing else about it moves:
   its own lines still sit 8 apart and the group step above it is the same as any other group's, so
   it is still a group of this system and not a new shape. Which groups qualify is written down in
   web/design-proposals/2026-09-09-secondary-page-system.md. */
.page-footnote,
.page-footnote p,
.page-footnote li,
.page-footnote h2 {
  font-size: var(--size-body-small);
  line-height: var(--line-body);
  color: var(--hotpot-text-secondary);
}

/* ==========================================================================
   3b. Lists and definition lists.

   A browser gives a list its own 1em above and below, which is a rung of nothing and COLLAPSES
   with whatever a sibling rule sets, so it comes off and the rules of section 3 own every gap
   around a list outright. No disc marker: web/DESIGN.md rule 7 bans dots, discs and small circles
   as decoration or markers everywhere outside the object's six controls. An ordered list keeps its
   numerals where they carry a sequence.

   A definition list is the group's three-part shape one level quieter: a term is apparatus, its
   statement sits 8 under it, and one entry to the next is the served-block step.
   ========================================================================== */

.page-list,
.page-defs {
  margin-block: 0;
}

.page-list {
  padding-left: var(--space-md);
}

ul.page-list {
  list-style: none;
}

.page-list li + li {
  margin-top: var(--space-xs);    /* 8 */
}

.page-defs > dt + dd,
.page-defs__item > dt + dd {
  margin-top: var(--space-xs);    /* 8, a term and its own statement */
}

.page-defs > dd + dt,
.page-defs > .page-defs__item + .page-defs__item {
  margin-top: var(--space-md);    /* 24, one entry to the next */
}

/* The row a page's control or controls stand in. It exists so a button is never dropped into a
   bare <p>: an inline-block that is taller than its line box leaves a few pixels of baseline slack
   under it, and that slack is a gap nobody chose sitting immediately above the page's one
   deliberate rest, which is exactly the passive space visual-rhythm rule 5 refuses. A flex row has
   no baseline slack, and it sets no margin of its own: the column's own step owns the gap above
   it, like every other sibling. (components.css's .section__actions is the same row for the band
   arrangement the secondary pages are being moved off; it carries a margin of its own and leaves
   with those pages.) */
.page-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

/* ==========================================================================
   4. The phone half of the ladder.

   The same four steps, one rung shorter each, at the breakpoint the header and the footer already
   change shape on, so the whole page changes arrangement once rather than in three places. Stated
   in em so a visitor at a raised text size reaches the phone ladder before the desktop one runs
   out of room.
   ========================================================================== */

@media (max-width: 47.999em) {
  .page-frame {
    padding-bottom: var(--space-xxl);            /* 48, and the footer's own 48 makes the 96 */
  }

  /* THE PHONE KEEPS THE 16 THE DESKTOP RULE ABOVE MOVED OFF: 16 is genuinely this width's
     within-a-group rung, so only the desktop half of that gap needed raising. */
  .page-masthead__row {
    padding-block-start: var(--space-sm);
  }

  .page-masthead__title,
  .page-masthead > h1 {
    margin-top: var(--space-sm);                 /* 16, within a group */
  }

  .page-column {
    margin-top: var(--space-xxl);                /* 48, between groups */
  }

  .page-column--opens {
    margin-top: var(--space-sm);                 /* 16, unchanged from the desktop */
  }

  /* The bottom rung is SHARED, 8 at both widths, which is what lets the phone read the hierarchy
     the desktop reads: every rung above it halves, this one does not. So the two-lines-of-one-
     register rule of section 3 needs no phone half at all, and only the wider steps are restated
     here. */

  .page-column > * + ul,
  .page-column > * + ol,
  .page-column > * + dl,
  .page-column > * + form,
  .page-column > * + .page-actions,
  .page-group > * + ul,
  .page-group > * + ol,
  .page-group > * + dl,
  .page-group > * + form,
  .page-group > * + .page-actions,
  .page-column > .page-lede + *,
  .page-group > .page-lede + * {
    margin-top: var(--space-sm);                 /* 16, a thing and what serves it */
  }

  .page-column > h2 + *,
  .page-group > h2 + * {
    margin-top: var(--space-xs);                 /* 8, a heading and its own line */
  }

  .page-column > .page-group + .page-group,
  .page-column > .page-open + .page-open,
  .page-column > .page-group + .page-open {
    margin-top: var(--space-xxl);                /* 48, between groups, three times the step inside */
  }

  .page-column > .page-open + .page-group {
    margin-top: var(--space-xxl);                /* 48, between groups */
  }

  .page-column > .page-group + .page-footnote,
.page-column > .page-open + .page-footnote {
    margin-top: calc(var(--space-lg) * 2);       /* 64, between sections */
  }

  .page-column > .page-group + .page-close,
  .page-column > .page-open + .page-close {
    margin-top: calc(var(--space-xxl) * 2);      /* 96, the one rest, down from 128 */
  }

  /* THE ENTRY STEP DOES NOT HALVE ON THE PHONE. A definition list is a group inside a group, so
     its entries have only the 8 between a term and its own statement to read against; at 16 the
     two are indistinguishable, which is what the founder saw at 390 ("contrast by gap works on
     safety desktop page, not on mobile page - photograph and prompt answer section and the space
     between elements has not hierarchy", ts 1788979346.549949). It stays 24 at both widths, three
     times the step inside an entry. */
  .page-defs > dd + dt,
  .page-defs > .page-defs__item + .page-defs__item {
    margin-top: var(--space-md);                 /* 24, one entry to the next, both widths */
  }
}
