/* ════════════════════════════════════════════════════════════════════════
   css/reference-pricing.css, /pricing only.
   service.tnaado.ca · loads AFTER css/reference.css, which owns the ground,
   the rail, the type scale, the buttons, the bone panel and the close.

   WHY A SECOND SHEET. /pricing is the only page on the site that is mostly
   columns of figures. Its ledgers, its arithmetic blocks and its tier cards
   are used nowhere else, and putting them in css/reference.css would ship
   them to /faq, /stack, /consulting and /strategy-publicity, none of which
   render a single price table.

   TABULAR FIGURES, EVERYWHERE. Every figure on this page sits in a column
   that has to align with the figure above it, so font-variant-numeric:
   tabular-nums is set on the ledger, on the arithmetic block and on the tier
   card rather than being remembered per cell. A proportional 1 next to a
   proportional 4 in a price column is how a reader stops trusting the
   arithmetic.

   THE TWO RULES THIS PAGE'S LAYOUT ENFORCES, from PRICES.md:

     1. A TIER'S CEILING IS A CAP, NOT A SUM. The tier card therefore has two
        separate slots: .tier__range for the band, and .tier__list for the
        contents priced at list rates. There is deliberately NO markup here
        that can print an equals sign between the maximum contents and the
        ceiling, because features are priced FROM $1,800 and rise, so the gap
        is real headroom.

     2. LOW TO HIGH. The three entry cards, the four tiers, the five monthly
        plans, the crew ladder, the cast ladder, the itemised list and the
        three packages are all ordered ascending in the MARKUP. Nothing here
        reorders visually, no flex-direction: row-reverse, no `order`, no
        grid-auto-flow trick, so the reading order and the DOM order are the
        same ascending order at every width and with no CSS at all.

   WIDE CONTENT. Every ledger and every arithmetic block lives inside
   .scroller (css/reference.css), which scrolls itself on overflow. The page
   body must never scroll sideways at 320px.
   ════════════════════════════════════════════════════════════════════════ */

/* ══ ACT ZERO · THE PRICE LADDER IN THE STORM ════════════════════════════
   BODY CHROME ONLY. The stage structure is css/scene.css, the camera is
   js/camera.js, the throw is js/bodies.js, the storm is js/tornado.js, and the
   one loop that drives all four is the inline boot at the foot of pricing.html.
   NOTHING IN THIS BLOCK POSITIONS, TRANSFORMS, HIDES OR CLIPS A [data-scene-body]
   outside .sc-live, because outside .sc-live this markup IS the page.

   This replaced the three static door cards. Same three figures, same ascending
   order, plus the four the reader previously had to scroll to find, and they
   now arrive rather than sit. PRICES.md governs the sequence, not taste: the
   first number a visitor meets is $44.99/month.

   THE REM RESCALE. Identical to /newsroom and /technology and it is load-bearing,
   not cosmetic: --sc-w is written in rem, so on a short viewport a plate sized
   min(21rem, 25vw) would keep its height while the stage lost it. Shrinking the
   root shrinks every plate on the stage together. Only under .sc-live, the
   static document is never rescaled. */
@media (max-height: 860px) { html.sc-live { font-size: 15px; } }
@media (max-height: 780px) { html.sc-live { font-size: 14px; } }
@media (max-height: 700px) { html.sc-live { font-size: 13px; } }

/* ── THE HEAD PLATE ────────────────────────────────────────────────────── */
.pr-head h1 { margin: .25rem 0 0; }
.pr-head .lede { margin-top: 1rem; }
.pr-head .crumb { margin: 0 0 .85rem; }

/* ── A FIGURE, AS AN OBJECT ────────────────────────────────────────────────
   An opaque ground, deliberately: a plate's contrast ratio is then fixed and is
   not a function of whatever the storm is doing behind it, which is why the
   renderer is allowed to run bright.

   NAMED pr-fig, NOT fig. `.fig` was already taken on this page, it is the
   LEDGER'S FIGURE COLUMN, declared further down this file, and the first
   version of this block called itself .fig, which silently drew a 1px box down
   both sides of every price cell in every price table on the page. Caught in
   the render, never visible in the source. Do not shorten it back. */
.pr-fig {
  background: var(--plate); border: 1px solid var(--hair-ink);
  border-top: 2px solid var(--red);
  padding: clamp(1.1rem, 2.4vw, 1.6rem);
  font-variant-numeric: tabular-nums;
}
.pr-fig__tag {
  margin: 0; font-family: var(--mono); font-size: .6875rem; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase; color: var(--red-ink);
}
/* Display type, so --red would be legal on it, it is bone anyway, because the
   figure is the thing to read and a price the reader squints at is a price he
   will not use. The red is spent on the rule above instead. */
.pr-fig__n {
  margin: .45rem 0 0; font-family: var(--serif); font-weight: 400;
  font-size: clamp(2.25rem, 5vw, 3.25rem); line-height: .98;
  letter-spacing: -.02em; color: var(--bone);
}
.pr-fig__of {
  margin: .4rem 0 0; font-family: var(--mono); font-size: .75rem; font-weight: 500;
  letter-spacing: .12em; text-transform: uppercase; color: var(--dim-ink);
}
.pr-fig__say { margin: .85rem 0 0; color: var(--dim-ink); font-size: .9375rem; }
/* THE ARITHMETIC LINE. The page's whole promise is that the sums check, so the
   two assembled figures carry theirs on the plate rather than in a paragraph
   somewhere else. Its own top rule, mono, tabular. */
.pr-fig__sum {
  margin: .95rem 0 0; padding-top: .85rem; border-top: 1px solid var(--hair-ink);
  font-family: var(--mono); font-size: .8125rem; line-height: 1.7;
  color: var(--dim-ink); font-variant-numeric: tabular-nums;
}
.pr-fig__sum b { color: var(--bone); font-weight: 500; }
.pr-fig--top { border-top-width: 3px; }

/* ── THE LANDING ───────────────────────────────────────────────────────── */
.pr-close {
  background: var(--plate); border: 1px solid var(--hair-ink);
  padding: clamp(1.35rem, 3vw, 2rem);
}
.pr-close h2 { margin: .5rem 0 0; font-size: clamp(1.5rem, 3.2vw, 2.125rem); }
.pr-close__say { margin: .9rem 0 0; color: var(--dim-ink); font-size: .9375rem; }
.pr-close .btns { margin-top: 1.35rem; }

/* ── THE STATIC STATE, WHICH IS THE BASE STATE ─────────────────────────────
   No JS, no WebGL2, reduced motion, or under 900px: `sc-live` is never added
   and the act is eight blocks in flow. Left as a column by css/scene.css that
   is eight plates tall, so the PARENT is re-laid out here, the parent, never
   the bodies, which css/scene.css forbids for good reason.

   The ladder keeps its ascending DOM order; grid never reorders it. */
html:not(.sc-live) .sc__space { max-width: var(--rail); padding-inline: var(--gut); }
html:not(.sc-live) .sc__cam {
  display: grid; gap: 1px;
  grid-template-columns: repeat(auto-fit, minmax(min(17rem, 100%), 1fr));
}
html:not(.sc-live) .sc__body { max-width: none; }
html:not(.sc-live) .pr-head,
html:not(.sc-live) .pr-close { grid-column: 1 / -1; }
html:not(.sc-live) .pr-head { padding-bottom: clamp(1rem, 2.5vw, 1.75rem); }
/* Hairline gaps rather than eight separate boxes, so the ladder reads as one
   object. The 1px grid gap does the drawing; the plates lose their own edges. */
html:not(.sc-live) .pr-fig { border: 0; box-shadow: inset 0 2px 0 var(--red); }
html:not(.sc-live) .sc__cam { background: var(--hair-ink); }
html:not(.sc-live) .pr-head,
html:not(.sc-live) .pr-close { background: var(--ink); }
html:not(.sc-live) .pr-close { border: 0; box-shadow: inset 0 1px 0 var(--hair-ink); }

/* ── THE LEDGER ────────────────────────────────────────────────────────── */
/* The page's workhorse: a label, an optional second line of detail, a figure.
   A table, because it is tabular data and a screen reader should be able to
   read a row as a row. Full-bleed hairlines, no card, no shadow, this is a
   price list and it should look like one. */
.ledger {
  width: 100%; border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}
.ledger caption {
  caption-side: top; text-align: left; padding: 0 0 .9rem;
  font-family: var(--mono); font-size: .75rem; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--dim-ink);
}
.ledger caption b { color: var(--bone); font-weight: 500; }
.ledger th, .ledger td {
  padding: .8rem .75rem; border-top: 1px solid var(--hair-ink);
  text-align: left; vertical-align: baseline;
}
.ledger th:first-child, .ledger td:first-child { padding-left: 0; }
.ledger tr > *:last-child { padding-right: 0; }
.ledger thead th {
  border-top: 0; border-bottom: 1px solid var(--hair-ink);
  font-family: var(--mono); font-size: .6875rem; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--dim-ink);
}
/* The row label. A <th scope="row">, so the figure beside it is announced with
   the thing it prices. */
.ledger tbody th {
  font-weight: 400; color: var(--bone); font-size: .9375rem;
  padding-right: 1.5rem;
}
.ledger tbody th b { font-weight: 600; }
.ledger tbody th small {
  display: block; margin-top: .2rem;
  font-size: .8125rem; color: var(--dim-ink); font-weight: 400;
}
/* THE FIGURE COLUMN. Mono and right-aligned, so the dollar signs stack and a
   reader can scan the column without reading the labels. */
.ledger .fig {
  width: 1%; white-space: nowrap; text-align: right;
  font-family: var(--mono); font-size: .9375rem; font-weight: 500;
  color: var(--bone); font-variant-numeric: tabular-nums;
}
.ledger .fig--soft { color: var(--dim-ink); font-weight: 400; }
.ledger tbody tr:hover th, .ledger tbody tr:hover td { background: var(--plate); }

/* ── ARITHMETIC ────────────────────────────────────────────────────────── */
/* An add-it-up block: rows, a rule, a total. The whole promise of this page is
   that the sums check, so the sums are shown as sums, and the total row is
   the only place a heavy rule appears, because that rule is the equals sign. */
.sum {
  margin: 1.5rem 0 0; padding: clamp(1.1rem, 2.2vw, 1.5rem);
  border: 1px solid var(--hair-ink); background: var(--plate);
  font-variant-numeric: tabular-nums;
}
/* The card title. h4 where an h3 group label sits above the card group
   (the tier-04 example, the monthly pair, the two media jobs); h3 where the
   cards hang straight off the section's h2, as they do in Combined packages.
   Both are listed so the outline can be correct without the type changing. */
.sum h3, .sum h4 {
  margin: 0 0 .9rem; font-family: var(--mono); font-weight: 500;
  font-size: .6875rem; line-height: 1.28; letter-spacing: .16em;
  text-transform: uppercase; color: var(--red-ink);
}
.sum table { width: 100%; border-collapse: collapse; }
.sum th, .sum td { padding: .5rem 0; text-align: left; vertical-align: baseline; }
.sum tbody th {
  font-weight: 400; color: var(--dim-ink); font-size: .9375rem; padding-right: 1.25rem;
}
.sum tbody th small { display: block; font-size: .8125rem; color: var(--dim-ink); }
.sum td {
  text-align: right; white-space: nowrap;
  font-family: var(--mono); font-size: .9375rem; color: var(--bone);
  font-variant-numeric: tabular-nums;
}
.sum tbody tr + tr th, .sum tbody tr + tr td { border-top: 1px solid var(--hair-ink); }
/* The total. A 2px red rule above it, a fill, which is what --red is for,
   and the figure at 24px, the floor at which #c8102e would itself be legal as
   type. It is bone rather than red anyway: the total is the thing to read. */
.sum tfoot th, .sum tfoot td {
  border-top: 2px solid var(--red); padding-top: .85rem;
}
.sum tfoot th {
  font-family: var(--mono); font-weight: 500; font-size: .75rem;
  letter-spacing: .14em; text-transform: uppercase; color: var(--dim-ink);
}
.sum tfoot td {
  font-family: var(--serif); font-size: clamp(1.5rem, 3vw, 1.875rem);
  line-height: 1.1; letter-spacing: -.015em; color: var(--bone);
}
/* A sub-heading that opens a card group inside a section that already has
   figures above it. Was an inline `style="margin-top:clamp(2rem,4vw,3rem)"`
   repeated on two h3s in pricing.html; one class so the value is declared
   once and lives with the rest of the sheet. */
.grouph { margin-top: clamp(2rem, 4vw, 3rem); }

/* A saving line: shown under a total, and the figure is always the exact
   difference between the two totals above it. PRICES.md: "every printed saving
   must be the exact difference. Check with a calculator, not by eye." */
.sum--pair { display: grid; gap: 1px; padding: 0; background: var(--hair-ink); }
.sum--pair > div { background: var(--plate); padding: clamp(1.1rem, 2.2vw, 1.5rem); }
@media (min-width: 52rem) { .sum--pair { grid-template-columns: 1fr 1fr; } }
.saving {
  margin: .9rem 0 0; padding-top: .85rem; border-top: 1px solid var(--hair-ink);
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: .8125rem; color: var(--dim-ink);
}
.saving b { color: var(--bone); font-weight: 500; }

/* ── TIER CARDS ────────────────────────────────────────────────────────── */
/* Four, ascending. Each carries a band, a name, what it is for, its maximum
   contents, the same contents priced at list rates, and a CTA matched to the
   band. THE BAND AND THE LIST-RATE FIGURE ARE TWO SEPARATE SLOTS and the
   markup never joins them with an equals sign. */
/* ══ THE BUILD TIERS, REDONE ═══════════════════════════════════════════
   Ethan: "pricing card section needfs to be redone."

   WHAT WAS WRONG, MEASURED. Two columns at 1440 gave four cards of 519x530px
   in a 2,193px section, so only two were ever on screen at once. Tiers exist to
   be COMPARED -- "one tier's ceiling is the next one's floor" is the section's
   own promise -- and a layout that shows two of four cannot deliver it. The
   reader had to scroll and remember.

   Four columns at >=72rem puts all four in one viewport. At 1440 that is about
   274px a card, which is wide enough for a 3-line description and a 3-item
   list, and the type scale below steps down to suit it.

   THE DEAD SPACE IS GONE. Each card was a plain flex column, so a card whose
   description ran two lines instead of three left a visible gap above its
   list-rate line while its neighbour did not. The rows now come from the GRID:
   `grid-template-rows: subgrid` makes every card share the container's five
   tracks, so range, name, description, list and figure align across all four
   whatever their content length. The @supports fallback keeps the old flex
   behaviour where subgrid is missing.

   THE FOUR BUTTONS ARE GONE. Every card carried its own CTA and all four
   pointed at the SAME url -- /contact?service=technology. Four buttons, one
   destination, is four times the noise for no extra choice. One CTA now sits
   under the rail. */
.tiers {
  display: grid;
  gap: 1px;
  margin: 2.25rem 0 0;
  background: var(--hair-ink);
  border: 1px solid var(--hair-ink);
}
@media (min-width: 40rem) { .tiers { grid-template-columns: 1fr 1fr; } }
@media (min-width: 72rem) { .tiers { grid-template-columns: repeat(4, 1fr); } }

/* THE DEAD SPACE, FIXED WITHOUT SUBGRID. Subgrid was the first attempt and it
   is the wrong tool here: it needs a fixed track count, and tier 04 carries one
   more paragraph than the other three, so a five-track span overflowed it.
   `margin-top: auto` on the list-rate line does the whole job -- it pushes that
   line to the foot of every card, so the four figures sit on one line and the
   slack collects ABOVE them instead of appearing as a ragged gap in whichever
   card happens to have the shortest description. That gap in tier 01 was the
   visible symptom. */
.tier__at { margin-top: auto; }
.tier {
  background: var(--plate); padding: clamp(1.15rem, 2vw, 1.5rem);
  display: flex; flex-direction: column; gap: .6rem;
  font-variant-numeric: tabular-nums;
}
.tier__n {
  margin: 0; font-family: var(--mono); font-size: .6875rem; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase; color: var(--red-ink);
}
/* The band, at display size, so --red is legal on it. Used as the section's
   loudest figure precisely because the reader's first question is "which of
   these am I". */
.tier__range {
  margin: 0; font-family: var(--serif); font-weight: 400;
  /* Stepped down from clamp(1.5rem, 2.9vw, 1.9375rem): at four-up a card is
     about 274px, and $18,000 to $45,000 wrapped mid-figure at the old size. */
  font-size: clamp(1.25rem, 1.9vw, 1.5rem); line-height: 1.1;
  letter-spacing: -.015em; color: var(--bone); font-variant-numeric: tabular-nums;
}
.tier__range em { font-style: italic; color: var(--bone-2); }
.tier h3 { margin: 0; }
.tier__for { margin: 0; color: var(--dim-ink); font-size: .9375rem; }
.tier__list { list-style: none; margin: .35rem 0 0; padding: 0; }
.tier__list li {
  position: relative; padding: .5rem 0 .5rem 1.4rem;
  border-top: 1px solid var(--hair-ink); font-size: .9375rem;
}
.tier__list li::before {
  content: ''; position: absolute; left: 0; top: 1rem;
  width: .5rem; height: 2px; background: var(--red);
}
/* The list-rate figure. Its own row, its own label, mono. It is NEVER printed
   as "= the ceiling" and it is never the loudest thing in the card. */
.tier__at {
  margin: auto 0 0; padding-top: .9rem; border-top: 1px solid var(--hair-ink);
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: .8125rem; color: var(--dim-ink);
}
.tier__at b { color: var(--bone); font-weight: 500; }
.tier .btn { margin-top: .35rem; align-self: flex-start; }

/* A POLICY CELL, NOT A PLAN. The monthly grid holds five plans in two columns,
   which left the right half of the last row as a filled grey box with nothing
   in it, a real fault, reported by Ethan and confirmed in the render. The cell
   now carries the supplier-overage rule from PRICES.md, which had to be
   published beside the monthlies anyway.

   It has to be legible as a rule rather than as a sixth plan, so it sits on the
   quieter --plate-2 ground with a red top edge, and its kicker names the plans
   it governs instead of a plan number. Everything else is the .tier card
   verbatim: a policy that looked like a different component would read as small
   print, and small print is what this rule must not be. */
.tier--policy {
  background: var(--plate-2);
  box-shadow: inset 0 2px 0 var(--red);
}
.tier--policy .tier__n { color: var(--dim-ink); }
.tier--policy .tier__range { color: var(--bone-2); }

/* ── TERMS ─────────────────────────────────────────────────────────────── */
.terms {
  list-style: none; margin: 2rem 0 0; padding: 0;
  display: grid; gap: 1px;
  grid-template-columns: repeat(auto-fit, minmax(min(19rem, 100%), 1fr));
  background: var(--hair-ink); border: 1px solid var(--hair-ink);
}
.terms li { background: var(--plate); padding: 1.15rem 1.25rem 1.35rem; }
.terms__n {
  display: block; font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: .6875rem; font-weight: 500; letter-spacing: .16em;
  color: var(--red-ink); margin-bottom: .45rem;
}
.terms h3 { font-size: 1.0625rem; font-family: var(--sans); font-weight: 600; letter-spacing: -.005em; }
.terms p { margin: .4rem 0 0; color: var(--dim-ink); font-size: .875rem; }

/* ── SECTION LEAD ──────────────────────────────────────────────────────── */
.plead { max-width: var(--measure); }
.plead h2 { margin: 0; }
.plead > p { margin: 1rem 0 0; }

/* A group CTA: one button and the address, sitting at the end of a price
   group so a reader who has found their figure does not have to scroll back to
   the top or on to the bottom to act on it. */
/* The rule above a group CTA belongs to the sentence under it, so it stops at
   the measure like every other prose rule on the page. */
.groupcta {
  margin: 2rem 0 0; padding-top: 1.5rem; border-top: 1px solid var(--hair-ink);
  display: grid; gap: .9rem; max-width: var(--measure);
}
.groupcta p { margin: 0; color: var(--dim-ink); font-size: .9375rem; }
.groupcta .btns { margin: 0; }
.groupcta .mailto { margin: 0; }

/* ── THE STORM READOUT ─────────────────────────────────────────────────────
   Off until ?hud=1 or the h key. Same block /technology carries, so a frame
   budget measured on one page is measured the same way on the other. */
.hud {
  display: none; position: fixed; right: 10px; bottom: 44px; z-index: 1300;
  font: 11px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre; color: var(--bone); background: rgba(0,0,0,.86);
  border: 1px solid var(--hair-ink); padding: 8px 10px; pointer-events: none;
}
.hud--on { display: block; }

/* ══ THE ALIGNMENT FAULTS ETHAN REPORTED ═════════════════════════════════
   "pricng page for tehc doesnt owrk is borken alignment and things arent
   matching". Two of the three he named were still live after the measure pass
   in css/reference.css; both are below, both measured in Chrome at 1440.

   1. A RULE RUNNING PAST THE THING IT CLOSES. .stamp and .groupcta both carry a
      border-top and both stop at --measure (704px). That is correct for a rule
      that underlines a paragraph, and wrong for these two, because each sits
      DIRECTLY BENEATH a full-rail ledger or card grid (1040px at 1440). The
      render showed a hairline stopping 336px short of the table above it, which
      reads as broken rather than as a reading measure.

      So the RULE spans the rail and the PROSE keeps the measure. A rule that
      closes a section is a section rule; the sentence under it is still prose.
      Nothing in css/reference.css changes, /faq, /stack, /consulting and
      /strategy-publicity have no price tables and keep the narrow rule. */
.stamp { max-width: none; }
/* `flex: 0 0 auto` was `flex-shrink: 0`, and a flex item that cannot shrink is a
   flex item that escapes. MEASURED at a 320 viewport: the rail's content box is
   280px, "Canadian dollars, before applicable taxes" has a 320px max-content in
   13px mono, and the span held all 320 of it, right edge 339.8 against a 320
   viewport, with body `overflow-x: visible` on this page so nothing masked it.
   documentElement.scrollWidth read 340: the PAGE scrolled sideways.

   `0 1 auto` keeps the basis (each fact still sits on one line and the row still
   wraps BETWEEN facts, which is what the original rule was for) and only lets an
   item shrink when it is alone on its line and still does not fit. Verified in
   Chrome: at 360, 390, 768 and 1440 every span's offsetWidth and right edge are
   unchanged to the pixel; at 320 the span goes 320 -> 280 and wraps its own text.
   `min-width: 0` clears the automatic min-content floor so the shrink can land. */
.stamp > span { flex: 0 1 auto; min-width: 0; }
.groupcta { max-width: none; }
.groupcta > p { max-width: var(--measure); }

/*  2. THE EMPTY FILLED GREY PANEL. .sum--pair is a two-column grid whose cells
      stretch, so when one column has four rows and the other has seven, the
      $95,000 example, the shorter cell painted the rest of its height as blank
      --plate. Ethan named it and the render confirmed it: roughly 130px of lit
      grey with nothing in it.

      Collapsing the cell is not the fix, because .sum--pair's own background is
      the hairline and an unstretched cell would show a solid grey band instead.
      The slack is given to the LAST BODY ROW instead, top-aligned, so it lands
      as breathing room immediately above the red total rule, and the two
      totals then sit on the same line, which is what a reader comparing two
      columns of arithmetic is trying to do anyway. */
.sum--pair > div { display: grid; grid-template-rows: auto 1fr; }
.sum--pair > div > table { height: 100%; }
.sum--pair tbody tr:last-child > * { height: 100%; vertical-align: top; }

/*  3. THE HOLES IN EVERY HAIRLINE GRID. Same fault as (2) and the same cause,
      found by re-rendering after the storm went in: css/reference.css draws
      .jump, .grid and .terms as a grid whose CONTAINER is the hairline colour
      with a 1px gap, and whose cells paint over it. That is elegant while the
      item count divides the column count and a lit grey rectangle the moment it
      does not, ten contents links in four columns leave two, thirteen terms in
      three columns leave two, three unit cards in two columns leave one.

      The hairlines move OFF the container and ONTO each cell as a 1px
      box-shadow, with the gap closed so adjacent shadows resolve to one line.
      An empty cell is then page ground and cannot be seen at all, at any count
      and any width. Scoped to this sheet, so /faq, /stack, /consulting and
      /strategy-publicity are untouched, they have the same construction and
      should probably get the same fix, but they are not this page. */
.jump, .grid, .terms { background: none; border: 0; gap: 0; }
.jump a, .card, .terms li { box-shadow: 0 0 0 1px var(--hair-ink); }

/* ══ THE DISCLOSURE SHELL ════════════════════════════════════════════════
   Ethan asked for "dynamic buttons/click to read more/dropdowns" by name, and
   this is the primitive the whole rebuild uses for them: <details>/<summary>.
   It works with no JavaScript, it is keyboard operable for free, the browser's
   own find-in-page opens it, and js/demos.js only READS the open state, it
   never controls it, so the disclosure and the demo inside it cannot fight.

   Nothing collapsed is removed from the DOM. The text is this page's proof and
   it stays indexable in both states.

   PORTED-COMPONENTS.md: ".tdx-row is not styled by demos.css, the summary
   chrome belongs to your page's own stylesheet." This is that chrome, matched
   to the harness so the two do not drift, plus a marker the harness did not
   need: on a reference page a control has to look like a control. */
.tdx-row { border-top: 1px solid var(--hair-ink); margin-top: clamp(2rem, 4vw, 3rem); }
.tdx-row > summary {
  list-style: none; cursor: pointer; padding: 1.1rem 0;
  display: flex; gap: 1rem; align-items: baseline;
  font-family: var(--mono); font-size: .78rem; letter-spacing: .06em;
  color: var(--dim-ink);
}
.tdx-row > summary::-webkit-details-marker { display: none; }
.tdx-row > summary b {
  color: var(--red-ink); font-weight: 500;
  font-variant-numeric: tabular-nums;
}
.tdx-row > summary:hover { color: var(--bone); }
.tdx-row > summary:focus-visible { outline: 2px solid var(--red-ink); outline-offset: 2px; }
/* The affordance. A plus that becomes a minus, drawn from two pseudo-elements
   rather than a glyph, because a glyph would need a font that carries it. */
.tdx-row > summary::after {
  content: ''; margin-left: auto; flex: 0 0 auto;
  width: .7rem; height: .7rem; align-self: center;
  background:
    linear-gradient(var(--red-ink), var(--red-ink)) center / 100% 1px no-repeat,
    linear-gradient(var(--red-ink), var(--red-ink)) center / 1px 100% no-repeat;
  transition: transform .2s var(--ease);
}
.tdx-row[open] > summary::after { background-size: 100% 1px, 1px 0; }
@media (prefers-reduced-motion: reduce) { .tdx-row > summary::after { transition: none; } }
.tdx-row__panel { padding: 0 0 .5rem; }

/* The cron stage's own scroll container, see the comment beside it in
   pricing.html. .scroller's default top margin would double the stage's, and a
   scroll container with no minimum width just shrinks its contents instead of
   scrolling, so the clock is given the width it actually needs. */
.job-scroll { margin-top: 0; }
.job-scroll > .job { min-width: 30rem; }
