/* =========================================================================
   ERISA Benefits Tech — account pages (SPEC-02)
   Loaded after style.css, which supplies the tokens, the reset, the nav and
   the footer. This file adds only what the account pages introduce.

   ⚠️ THIS FILE EXISTS BECAUSE THE PAGES CARRY NO INLINE STYLE.
   SPEC-02 §7.1's Content-Security-Policy is default-src 'self' with no
   'unsafe-inline', so a style attribute or a <style> block is dropped by the
   browser IN SILENCE. The seven static marketing pages use inline style
   attributes freely; the account pages cannot, and every rule they need is
   here instead. Adding one inline later will not error — it will simply stop
   applying, which is the failure mode as-built Part 8 spends a page on.

   ⚠️ NO @import, NO url() TO ANOTHER HOST. Privacy Notice §3.4 and §7.1, and
   SPEC-02 §1.8: a webfont or image fetched from a CDN discloses the visitor's
   IP address and the page URL to a processor §8.1 does not name. The account
   pages deliberately do not load the Google Fonts the static pages load, and
   style.css already declares full local fallback stacks for all three faces.
   ========================================================================= */

/* ---- The registration page's introductory copy -------------------------- */
.lede p { margin: 0 0 .8rem; }

/* The sign-in offer at the head of the registration page (SPEC-09). Quiet -
   this page's job is still registration - but unmissable, which the one at the
   foot of the page is not. */
.signin-top {
  margin: -.5rem 0 1.5rem;
  padding: .65rem .95rem;
  background: var(--ice);
  border-left: 3px solid var(--gold);
  border-radius: 0 4px 4px 0;
  font-size: .95rem;
  max-width: 34rem;
}

/* ---- Forms -------------------------------------------------------------- */
/* ⚠️ THE CAP MOVED FROM THE FORM TO THE FIELD - SPEC-09, and it is the fix for
   the narrow document boxes rather than a change to the form itself.
   `.account-form { max-width: 34rem }` capped EVERYTHING inside the form,
   including the <fieldset> holding the inlined instruments - so the Account
   Terms and the Privacy Notice were being read through a 544px window on a
   1240px page, and so were the three documents at purchase.
   A text input SHOULD be about 34rem: a full-width e-mail field on a wide screen
   looks broken and is harder to aim at. A published instrument should not be.
   So the input keeps the measure and the form does not. */
.account-form { max-width: none; margin: 1.75rem 0 0; }
.account-form .field { margin-bottom: 1.25rem; max-width: 34rem; }
.account-form > p,
.account-form > .form-note { max-width: var(--measure); }
.account-form label { display: block; font-weight: 500; margin-bottom: .35rem; }
.account-form input[type="text"],
.account-form input[type="email"],
.account-form input[type="password"] {
  width: 100%;
  padding: .65rem .75rem;
  font: inherit;
  color: var(--ink);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 3px;
}
.account-form input:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
  border-color: var(--gold);
}
.account-form .form-note { margin: .4rem 0 0; }
.account-form button { margin-top: .5rem; }

.inline-form { margin-top: .75rem; }

/* Checkbox rows: the control and its label side by side, the label wrapping
   under itself rather than under the box. */
.check { display: flex; gap: .65rem; align-items: flex-start; }
.check input[type="checkbox"] { margin-top: .3rem; flex: 0 0 auto; width: 1.05rem; height: 1.05rem; }
.check label { font-weight: 400; margin: 0; }

/* ---- The tier chooser on the purchase page -------------------------------
   See the long note in page-purchase.php for what was wrong here. In short:
   this fieldset carried the marketing page's three-column card grid, so the
   legend, the notes and two quoted contract sections were dealt into columns
   alongside the options. It is a stack of full-width rows now.

   ⚠️ `.tier-choice` AND `.tierlist` (style.css) ARE DELIBERATELY DIFFERENT
   NAMES FOR THE TWO PLACES TIERS APPEAR. One is a form control, one is a
   marketing list. They looked similar enough to share a class once already. */
.tier-choice { display: block; }
.tier-choice .form-note { max-width: var(--measure); }

.account-form .tier-option {
  padding: .95rem 1.1rem;
  margin: .7rem 0 0;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--white);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.account-form .tier-option:hover { border-color: #b9c2d8; }
/* The whole row reads as selected, not just the radio. :has() is progressive -
   where it is unsupported the row simply looks unselected and the radio still
   shows the state, which is the pre-SPEC-09 behaviour. */
.account-form .tier-option:has(input:checked) {
  border-color: var(--gold);
  box-shadow: inset 3px 0 0 var(--gold);
}
.account-form .tier-option input[type="radio"] { margin-top: .35rem; flex: 0 0 auto; width: 1.05rem; height: 1.05rem; }
.account-form .tier-option label { display: grid; grid-template-columns: 1fr; gap: .25rem .5rem; width: 100%; }
@media (min-width: 46rem) {
  .account-form .tier-option label { grid-template-columns: minmax(0, 1fr) 9rem; align-items: start; }
  .tier-price { text-align: right; }
}
.tier-name { font-size: 1.08rem; color: var(--navy); }
.tier-price { font-family: var(--serif); font-size: 1.5rem; color: var(--navy); line-height: 1.1; white-space: nowrap; }
.tier-option--unavailable .tier-price { font-family: var(--sans); font-size: .92rem; color: var(--steel); font-weight: 500; }
.tier-option--unavailable { background: #fbfcfe; }
.tier-main .form-note { display: block; margin: .25rem 0 0; }

/* The two quoted sections of the Agreement, below the options. Set apart from
   the form so it is obvious they are quotations from the instrument rather than
   the site's own explanation of it. */
.quoted-term {
  margin: 1.1rem 0 0;
  padding: .85rem 1.1rem;
  background: var(--ice);
  border-left: 3px solid var(--gold);
  border-radius: 0 4px 4px 0;
  font-size: .94rem;
  max-width: var(--measure);
}
.quoted-term p { margin: 0 0 .45rem; }
.quoted-term p:last-child { margin-bottom: 0; }

/* ---- Assent and marketing: separate, and visibly so ---------------------
   SPEC-02 §3.3 requires the marketing control to be "visually and structurally
   separate" from the assent control and not a sub-item of it. Two fieldsets,
   two legends, two boxes, different weights. This is a published-term
   requirement wearing the clothes of a styling choice; do not merge them to
   tidy the page up. */
.account-form fieldset {
  margin: 1.75rem 0;
  padding: 1.15rem 1.25rem;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--white);
}
.account-form legend {
  padding: 0 .5rem;
  font-family: var(--mono);
  font-size: .78rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--steel);
}
.account-form fieldset.assent { border-color: var(--navy); }
.assent-text {
  margin: 0 0 1rem;
  font-size: 1.0625rem;
  line-height: 1.6;
  color: var(--ink);
}
.account-form fieldset.marketing { background: var(--ice); }

/* ---- The inline document regions ----------------------------------------
   Each independently scrollable, each labelled, neither truncated. The height
   is generous on purpose: BUILD-REQ §1 wants the text readable in place, and a
   four-line window technically satisfies "present in the response" while
   making the document unreadable.

   ⚠️ SPEC-09 REBUILT THE PRESENTATION OF THESE BOXES AND CHANGED NOTHING ABOUT
   WHAT IS IN THEM. The bytes are still documents_text($key), still inlined
   unescaped, still the same read of the same manifest that reaches
   assent_record(). Four presentation problems were fixed:

     1. THE BOX HAD NO VISIBLE START OR END. A 1px hairline in the same colour
        as every other hairline on the page, with the instrument's own <h1>
        inside it, so a reader could not tell where a published document began
        and the site resumed. There is now a titled header bar, a firmer border,
        and a footer that says the document has ended.

     2. IT WAS SET AT BODY SIZE AND BODY LEADING. 1.0625rem at the old 1.65 for
        a 12-section instrument. Now .86rem at 1.38 - smaller and effectively
        single spaced, which is how a document of this kind is normally set and
        which fits about half again as much of it in the same window.

     3. THERE WAS NO SIGNAL THAT THE BOX SCROLLS. Solved with the four-layer
        background below: two solid strips that scroll with the content and two
        shadows fixed to the frame, so a shadow shows at an edge only when there
        is more text past it. `background-attachment: local, local, scroll,
        scroll` is what pins the pairs differently; it is not decoration and
        should not be simplified away.

     4. IT WAS 544px WIDE. That was the .account-form cap, fixed above.

   ⚠️ DO NOT ADD A CLASS TO THE .document-scroll DIV OR THE .document-region
   SECTION. Acceptance rows 106, 304 and 313 match `class="document-region"` and
   `class="document-scroll"` as literal strings, and row 113 strips the
   instruments out of the urgency scan with a regex anchored on the second. The
   new furniture is a WRAPPER and two SIBLINGS, which those patterns do not see. */
.documents { padding-top: .5rem; }

/* The frame: header bar, scroller, footer. */
.document-region { margin: 1.75rem 0 0; border: 1px solid #b9c2d8; border-radius: 6px; overflow: hidden; background: var(--white); }
.document-head {
  background: var(--ice); border-bottom: 1px solid #b9c2d8;
  padding: .7rem .95rem;
}
.document-head h1,
.document-head h2 { font-size: 1rem; margin: 0 0 .15rem; }
.document-meta { margin: 0; font-family: var(--mono); font-size: .7rem; letter-spacing: .03em; color: var(--steel); line-height: 1.5; }
.document-note { margin: .45rem 0 0; font-size: .82rem; line-height: 1.4; color: var(--ink); }

.document-scroll {
  max-height: 30rem;
  overflow-y: auto;
  padding: 1rem 1.25rem;
  border: 0;
  border-radius: 0;
  background:
    linear-gradient(var(--white) 30%, rgba(255,255,255,0)) top / 100% 20px no-repeat,
    linear-gradient(rgba(255,255,255,0), var(--white) 70%) bottom / 100% 20px no-repeat,
    radial-gradient(farthest-side at 50% 0, rgba(14,18,48,.10), transparent) top / 100% 7px no-repeat,
    radial-gradient(farthest-side at 50% 100%, rgba(14,18,48,.10), transparent) bottom / 100% 7px no-repeat;
  background-color: var(--white);
  background-attachment: local, local, scroll, scroll;
  font-size: .86rem;
  line-height: 1.38;
}
.document-scroll:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }

/* "You have reached the end of this document." Cheap to render and it answers
   the question the old box left open. */
.document-foot {
  border-top: 1px solid #dfe4ef; background: #fafbfe;
  padding: .5rem .95rem;
  font-family: var(--mono); font-size: .66rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--steel);
}

/* ---- The generated instrument text --------------------------------------
   These rules replace the <style> block that Website/documents/*.html used to
   carry inside itself. The documents are now body fragments so they can be
   inlined byte-for-byte on register.php (SPEC-02 §4.1) and so they satisfy
   acceptance row 8, which forbids <style>, <script> and style attributes in
   them. The presentation moved here; the instrument text did not change. */
.ebt-document { max-width: 44rem; margin: 0 auto; font-family: var(--serif); }
.ebt-document h1 { font-size: 1.3rem; letter-spacing: .03em; margin: 0 0 .25rem; }
.ebt-document h2 { font-size: 1.02rem; margin: 1.75rem 0 .5rem; }
.ebt-document p { margin: 0 0 .85rem; line-height: 1.65; }

/* ⚠️ THE SAME INSTRUMENT, SET TWO WAYS, AND ON PURPOSE.
   On document.php the instrument IS the page, so it keeps the centred 44rem
   column and the comfortable leading above. Inside a scroll box on the
   registration or purchase form it is one of two or three documents the reader
   has to get through before a checkbox, and there the job is to fit as much of
   it in view as can still be read: left-aligned, a longer measure, and single
   spacing. The rules below apply ONLY inside .document-scroll. */
.document-scroll .ebt-document { max-width: 90ch; margin: 0; }
.document-scroll .ebt-document h1 { font-size: 1.05rem; }
.document-scroll .ebt-document h2 { font-size: .92rem; margin: 1.15rem 0 .35rem; }
.document-scroll .ebt-document p { margin: 0 0 .5rem; line-height: 1.38; }
.document-scroll .ebt-document .titleblock { margin-bottom: 1.1rem; padding-bottom: .7rem; }
.document-scroll .ebt-document .meta { font-size: .8rem; }
.ebt-document .meta { color: var(--steel); font-size: .9rem; margin: 0; }
.ebt-document .titleblock {
  margin-bottom: 1.75rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--line);
}

/* document.php — the standalone rendering. Same text, no scroll box. */
.document-standalone .document-full { margin-top: 1.5rem; }
.document-plain {
  margin-top: 1.5rem;
  padding: 1.25rem;
  overflow-x: auto;
  white-space: pre-wrap;
  word-break: break-word;
  font-family: var(--mono);
  font-size: .9rem;
  line-height: 1.6;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 3px;
}
.presentation-note { margin-top: 1.25rem; }

/* ---- Messages -----------------------------------------------------------
   Colour is never the only signal: the error box carries role="alert" and the
   notice carries role="status", and both are introduced by their own words. */
.formerror, .formnotice {
  margin: 1.5rem 0;
  padding: 1rem 1.25rem;
  border-radius: 4px;
  border-left: 4px solid;
}
.formerror  { background: #fdf3f2; border-color: #a4262c; }
.formnotice { background: var(--ice); border-color: var(--navy); }
.formerror p:last-child, .formnotice p:last-child { margin-bottom: 0; }
.formerror ul, .formnotice ul { margin: .5rem 0 0; padding-left: 1.2rem; }

/* ---- Account page panels ------------------------------------------------ */
.panel {
  margin: 1.75rem 0;
  padding: 1.25rem 1.5rem;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 4px;
}
.panel h2 { font-size: 1.1rem; margin: 0 0 .75rem; }
.panel p:last-child { margin-bottom: 0; }

.details { display: grid; grid-template-columns: 10rem 1fr; gap: .4rem 1rem; margin: 0 0 1rem; }
.details dt { font-family: var(--mono); font-size: .8rem; letter-spacing: .05em;
              text-transform: uppercase; color: var(--steel); }
.details dd { margin: 0; word-break: break-word; }

@media (max-width: 34rem) {
  .details { grid-template-columns: 1fr; gap: 0 0; }
  .details dd { margin-bottom: .75rem; }
}

.alt-actions {
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
}
.alt-actions h2 { font-size: 1.05rem; margin: 0 0 .5rem; }

/* ===========================================================================
   SESSION THREE - the account area, the training gate, and the admin console.
   SPEC-03 1.9.

   NO @import AND NO url() TO ANOTHER HOST, anywhere in this file. Acceptance
   rows 159 and 255 scan for both. Privacy Notice §3.4 says EBT uses no
   third-party trackers and §8.1 names the processors; a webfont or an image
   fetched from a CDN discloses the visitor's IP address and the page URL to a
   host named in neither. The CSP on every .php page makes that mechanical
   rather than remembered - default-src 'self' blocks it - but this file is
   loaded by the static pages too, where the CSP does not yet reach.

   Every colour and measure below is an existing custom property from
   style.css. Nothing here introduces a new token.
   =========================================================================== */

/* --- shared -------------------------------------------------------------- */

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

.field-error { color: #a12; font-size: .85rem; margin: -.5rem 0 1rem; }

.formnotice--error { border-left-color: #a12; }

/* A panel that carries something requiring attention: an unmet obligation, or
   a control that cannot be undone. Deliberately quiet rather than alarming -
   the destructive forms carry their own prose, and colour that shouts on every
   visit stops being read. */
.panel--alert { border-left: 3px solid var(--gold); }

.table { width: 100%; border-collapse: collapse; margin: 0 0 1rem; font-size: .9rem; }
.table th, .table td { text-align: left; padding: .5rem .6rem; vertical-align: top;
                       border-bottom: 1px solid var(--line); }
.table th { font-family: var(--mono); font-size: .75rem; letter-spacing: .05em;
            text-transform: uppercase; color: var(--steel); font-weight: 600; }
.table td .form-note { display: block; margin: .2rem 0 0; }

/* Tables of Releases and audit rows are wide and the wrap is narrow. Scroll the
   table rather than the page. */
@media (max-width: 46rem) {
  .table { display: block; overflow-x: auto; white-space: nowrap; }
}

.btn--small { padding: .25rem .6rem; font-size: .8rem; }

/* The §10.1 export and the address list: plain text, shown as plain text. */
.export {
  background: var(--ice); border: 1px solid var(--line); border-radius: 3px;
  padding: 1rem; overflow-x: auto; font-family: var(--mono); font-size: .8rem;
  line-height: 1.5; white-space: pre-wrap; word-break: break-word;
}

/* --- the training -------------------------------------------------------- */

/* ⚠️ THE MODULE BODY IS TRUSTED HTML AND ITS PROSE CARRIES NO CLASSES OF ITS OWN.
   It is authored as plain h2/h3/p/ul/ol/blockquote/pre and dressed from here,
   which is what lets the body files stay free of the inline styles and <style>
   blocks the CSP would silently drop. training_body_problem() refuses all three
   at the publication gate.

   ⚠️ SPEC-10 ADDS ONE EXCEPTION AND IT IS A CLOSED ONE: the lm- diagram
   vocabulary at the foot of this file. A body may use those class names and no
   others. The exception exists because an animation has to be driven from a
   stylesheet - there is no other route past the CSP, and no other route that can
   honour prefers-reduced-motion. Prose is still classless. */
.ebt-module { margin: 1.5rem 0 2rem; }
.ebt-module h2 { font-family: var(--serif); font-size: 1.35rem; margin: 1.75rem 0 .75rem; }
.ebt-module h2:first-child { margin-top: 0; }
.ebt-module h3 { font-size: 1.05rem; margin: 1.5rem 0 .5rem; color: var(--navy); }
.ebt-module p { margin: 0 0 1rem; line-height: 1.7; }
.ebt-module ul, .ebt-module ol { margin: 0 0 1rem 1.25rem; line-height: 1.7; }
.ebt-module li { margin-bottom: .5rem; }
.ebt-module blockquote {
  margin: 1.25rem 0; padding: .75rem 1rem; border-left: 3px solid var(--gold);
  background: var(--ice); font-style: italic;
}
.ebt-module pre {
  background: var(--ice); border: 1px solid var(--line); border-radius: 3px;
  padding: .75rem 1rem; overflow-x: auto; font-family: var(--mono); font-size: .82rem;
}
.ebt-module code { font-family: var(--mono); font-size: .88em; }

.module-nav { display: flex; gap: .75rem; flex-wrap: wrap; align-items: center;
              margin: 2rem 0 1rem; padding-top: 1.25rem; border-top: 1px solid var(--line); }
.module-nav form { margin: 0; }

/* The seven Account Terms statements. On every gated training page, every
   section - acceptance row 225. Set apart from the material without being
   dismissible, because each one is a published term operating where it
   operates. */
.panel--terms { background: var(--ice); }
.terms-list { margin: 0; padding-left: 1.1rem; }
.terms-list li { margin-bottom: .75rem; line-height: 1.6; font-size: .92rem; }
.terms-list li:last-child { margin-bottom: 0; }

/* --- the admin console --------------------------------------------------- */

/* ⚠️ THE ADMIN NAVIGATION IS THE ONLY PLACE /admin/ IS LINKED FROM. No public
   page and no member page links to it - acceptance row 249 - and robots.txt is
   not modified, because a Disallow line publishes the path to everyone who
   reads the file. The noindex header plus no inbound link is the control, and
   admin_require()'s exact 403 is the security. */
.admin-nav {
  display: flex; gap: 1rem; flex-wrap: wrap; margin: 0 0 2rem;
  padding-bottom: .75rem; border-bottom: 1px solid var(--line);
  font-family: var(--mono); font-size: .8rem; letter-spacing: .04em;
  text-transform: uppercase;
}
.admin-nav a { color: var(--steel); text-decoration: none; }
.admin-nav a:hover, .admin-nav a:focus { color: var(--navy); text-decoration: underline; }

/* One unmet §8.2 notice on the overview. Separated so several read as several
   rather than as a wall. */
.obligation {
  margin: 0 0 1.25rem; padding: 0 0 1.25rem;
  border-bottom: 1px solid var(--line);
}
.obligation:last-child { border-bottom: 0; padding-bottom: 0; margin-bottom: 0; }
.obligation .account-form { margin-top: .5rem; }

/* =========================================================================
   SPEC-10 - the lm- (learn-module) diagram vocabulary
   =========================================================================

   ⚠️ THIS LIST IS CLOSED. A module body may use these class names and no
   others. A body that wants a new one does not get to invent it - the class is
   added here first, deliberately, and acceptance row D fails a body that uses
   an lm- class this file does not define.

   ⚠️ EVERY ANIMATED RULE MUST APPEAR IN THE REDUCED-MOTION BLOCK AT THE FOOT
   OF THIS SECTION. That is acceptance row E, and it is the reason the block is
   kept adjacent to the keyframes rather than filed with the other media
   queries: the two are edited together or the second is forgotten.

   ⚠️ AND THE ANIMATION NEVER CARRIES A FACT. Every distinction a diagram makes
   is encoded statically - fill, stroke, dash - so that the still frame a
   reduced-motion reader sees is the whole diagram rather than a degraded one.
   Motion only sequences attention. That is SPEC-09 Part 3's rule (a drawing
   carries no fact the prose does not) applied one level down, to the drawing's
   own moving parts. */

.lm-fig { margin: 1.75rem 0; }
.lm-diagram { display: block; width: 100%; height: auto; max-width: 45rem; margin: 0 auto; }
.lm-cap {
  margin: .65rem auto 0; max-width: 34rem;
  font-size: .84rem; line-height: 1.5; color: var(--steel); text-align: center;
}

/* Geometry. --- lm-node is the DASHED state on purpose: a heading the answer
   never reached is drawn as provisional, not as wrong. lm-node-no is the
   refused/never state and is the only place brass carries a negative. */
.lm-link    { fill: none; stroke: #c3cbdd; stroke-width: 1; }
.lm-head    { fill: #c3cbdd; stroke: none; }
.lm-rule    { fill: none; stroke: #b9c2d8; stroke-width: 1; }
.lm-mark    { fill: none; stroke: var(--gold); stroke-width: 2; }
.lm-strike  { fill: none; stroke: var(--gold); stroke-width: 1.5; }
.lm-ask     { fill: var(--ice); stroke: #b9c2d8; stroke-width: 1; }
.lm-node    { fill: var(--white); stroke: #b9c2d8; stroke-width: 1; stroke-dasharray: 4 3; }
.lm-node-on { fill: var(--navy); stroke: var(--navy); stroke-width: 1; }
.lm-node-no { fill: var(--white); stroke: var(--gold); stroke-width: 1.5; }

/* ⚠️ THE DRAWN-INTERFACE VOCABULARY - SPEC-10 B4, AND THE THREE PROPERTIES ARE
   A SET. Faithful in layout, labels and sequence; OBVIOUSLY DRAWN - flat brand
   colour, hairline strokes, NO gradients, NO shadows, NO window chrome, no
   attempt at a screenshot's texture; and dated, in a figcaption, by the body.
   A reader must never wonder whether they are looking at a photograph of a
   screen. Do not add a shadow to any of these to make them look "real". */
.lm-ui       { fill: var(--white); stroke: #b9c2d8; stroke-width: 1; }
.lm-ui-side  { fill: var(--ice); stroke: none; }
.lm-ui-panel { fill: var(--white); stroke: #cdd5e6; stroke-width: 1; }
.lm-ui-field { fill: var(--white); stroke: #b9c2d8; stroke-width: 1.5; }
.lm-ui-btn   { fill: var(--navy); stroke: none; }
.lm-ui-chip  { fill: var(--ice); stroke: #cdd5e6; stroke-width: 1; }
.lm-step     { fill: var(--gold); stroke: none; }

/* Type inside a diagram. Sized in px against the viewBox, not in rem: the SVG
   scales as a unit and rem would break the layout at small widths.

   ⚠️ THE NUMBER THAT MATTERS IS THE RATIO OF TYPE SIZE TO viewBox WIDTH, NOT
   THE PIXEL VALUE, because the SVG is scaled to its container before anyone
   reads it. index.html's plates set 13.5px in a 560-wide box - about 0.024 -
   and that is the house figure. A diagram drawn wider than it needs to be
   silently shrinks its own labels below that on a phone. Keep the viewBox as
   narrow as the layout allows and check the ratio, not the font-size. */
.lm-t       { fill: var(--ink); font-family: var(--sans); font-size: 14px; }
.lm-t-on    { fill: var(--white); font-family: var(--sans); font-size: 14px; }
.lm-t-k     { fill: var(--gold); font-family: var(--sans); font-size: 11.5px; letter-spacing: .07em; }
.lm-t-on-k  { fill: var(--muted-navy); font-family: var(--sans); font-size: 11.5px; letter-spacing: .07em; }
.lm-t-ui    { fill: var(--steel); font-family: var(--sans); font-size: 13px; }
.lm-t-step  { fill: var(--white); font-family: var(--sans); font-size: 12px; font-weight: 600; }

/* ⚠️ THE DIAGRAMS ARE STATIC. THE ANIMATION WAS REMOVED ON 17 AUGUST 2026, ON
   ERWIN'S INSTRUCTION, AND REMOVING IT COST NOTHING.

   That is not a consolation - it is a fact about how these diagrams were built.
   Every distinction any of them makes is encoded STATICALLY: fill, stroke, dash.
   Motion only ever sequenced attention, because SPEC-09 Part 3's rule (a drawing
   carries no fact the prose does not) was applied to the drawing's own moving
   parts as well. So the still frame was always the whole diagram, and it still
   is. Nothing was lost by stopping it moving.

   ⚠️ WHY IT WENT: it could not be made to fire when a reader actually looked at
   it. From page load it had finished before anyone scrolled down; keyed to
   scroll it could not be verified in a headless session; and Erwin's judgement
   was that chasing it further would cost hours for a poor result. He is right,
   and the diagrams read perfectly without it.

   ⚠️ THE .lm-cue-N RULES STAY DEFINED AND MUST. The bodies still carry the cue
   rectangles, and acceptance row 229d fails a body using an lm- class this file
   does not define. Removing these rules would therefore turn six published
   modules red - and EDITING the bodies to strip the rectangles would change
   their bytes, revert every published module to draft, and cost another round of
   §3.1 review sittings. Leaving invisible markup in place is much the cheaper
   correctness.

   ⚠️ AND THIS IS THE HOOK IF ANIMATION EVER COMES BACK. The rectangles are
   already positioned behind the right nodes in all 21 diagrams. A click-to-play
   control - a relative #fragment link and a :target rule, which needs no
   JavaScript and so passes training_body_problem() - would only have to give
   these three rules an animation again. */
.lm-cue   { fill: none; stroke: var(--gold); stroke-width: 2; opacity: 0; }
.lm-cue-1 { animation: none; }
.lm-cue-2 { animation: none; }
.lm-cue-3 { animation: none; }

@media (prefers-reduced-motion: reduce) {
  /* Nothing in the lm- vocabulary animates today - see the note above the
     cue rules. This block is kept, empty of cue rules, because account.css
     had no reduced-motion block at all before SPEC-10 and the next person to
     add an animation needs somewhere obvious to put its counterpart. */
}
