/**
 * patterns.css — house PATTERNS: markup shapes every surface writes the same way.
 *
 * WHY THIS FILE EXISTS (Ramés, 2026-09-10): "tudo recebe do design system e é o mesmo elemento
 * independente da superfície." A pattern is not a component (no shadow root, no behaviour, no
 * API) and not a token (not a value). It is a SHAPE — `.chap` is a grid with an icon column, a
 * title row and a subtitle row — that marketing, the showcase and the vault all write in their
 * markdown, and that until today each of them styled from its own sheet.
 *
 * WHY NOT IN `tokens.css`, and the reason is not size: a `tokens.css` that stops being only
 * tokens stops being a contract. Dev CO measured the other half — the extra `<link>` costs
 * 29.6 KB on the wire for 87.7 KB on disk (34%), the sheets finish at 29 ms against a
 * first-contentful-paint at 124 ms — so the link was never the argument either way.
 *
 * WHY NOT IN A SKIN: a pattern must hold under all fourteen. Specificity keeps the order safe:
 * `.chap` is (0,1,0) and any skin that touches it writes `:root[data-skin="x"] .chap` at
 * (0,2,1), so a skin wins by SPECIFICITY and not by link order — the seam may place this sheet
 * wherever it likes between the tokens and the skins.
 *
 * THE `article` ANCESTOR IS GONE FROM EVERY SELECTOR and that is the move, not a tidy-up. In
 * `marketing.css` every rule read `article .chap`, because on that surface the panel always sat
 * inside Quartz's `<article>`. The vault's document page puts the same panel outside one. A
 * pattern that requires its host's wrapper is not a pattern.
 *
 * THE TYPOGRAPHY IS PINNED HERE, which is the defect this move closes. `h2`/`h3.sub` inside the
 * panel used to inherit from each surface's own `index.css`; measured on 2026-09-12 the two
 * served surfaces agreed, so nothing was broken yet — but "nothing is broken yet" is what a
 * risk looks like from inside. The values are Copy Chief's measurement of see.md and the mock
 * at the same viewport, where they already agreed: h2 22.4px/700, h3.sub 12px uppercase at
 * .08em, the two 2px apart, icon 36px in a 3.4rem column.
 */

/* ============================================================================
   THE CHAPTER IS A PANEL, AND THAT ALSO RETIRES THREE MAGIC NUMBERS.

   THE DIAGNOSIS WAS AN INVERTED HIERARCHY, not a missing divider. Rendered, the page read
   heading / floating prose / CONTAINED FIGURE / floating prose: the figure carried a border,
   a fill and a blur while the chapter that owns it carried nothing, so the strongest container
   on the page was a child of the section rather than the section. Prose did not read loose so
   much as OUT-RANKED.

   Now each chapter is a real element, which fixes the ranking AND the alignment at once:

   1. THE CHAPTER IS THE SURFACE. Soft ground, hairline border, radius, generous padding.
   2. THE FIGURE GIVES BACK ITS FILL and keeps only its outline, so it reads as an object
      INSIDE the panel instead of a competing surface. The blur goes with the fill: a backdrop
      filter over a transparent box is cost with no picture.
   3. THE ICON SITS IN ITS OWN GRID COLUMN, vertically centred on the title block by the
      layout rather than by an offset. Everything before this was a magic number chasing a
      MARGIN COLLAPSE: `.ch` was a zero-height div and the h2's top margin collapsed through
      it, so the icon's 18px raise was EMERGENT, and every spacing change moved it. Measured,
      three times: padding opened a 2.4rem gap; a margin dropped it 19px; a margin on the
      previous paragraph did the same. The wrapper removes the collapse from the problem.
   ============================================================================ */
.chap{position:relative;display:grid;grid-template-columns:3.4rem 1fr;
  gap:0 0;align-items:start;
  /* ONE RADIUS FOR EVERY COMPONENT, ruled by @rames 2026-08-29 -- this panel was 14 while
     the vault panel was 10, the toolbar 8, the search box 7, the graph 5 and the rail 4.
     Six values reading as six decisions when they were six defaults. The token is the
     vault panel's, which is the one he named. */
  border:1px solid color-mix(in srgb,var(--lightgray) 85%,transparent);border-radius:var(--sz-glass-radius,10px);
  background:transparent;
  padding:1.7rem 1.9rem 1.5rem;margin:1.6rem 0}
/* THE GLASS IS A VEIL, NOT A FILTER ON THE PANEL, AND THAT IS A MEASURED CORRECTION.
   `blur(4px)` is the house's own value, read off the served page from `div.search-container`
   and `div.global-graph-outer`, the only two elements that already carry a backdrop filter.
   PUT IT ON `.chap` DIRECTLY AND THE COMPARE MODAL BREAKS: `backdrop-filter` makes the element
   a containing block for `position:fixed` DESCENDANTS, and the modal lives inside this panel.
   Measured before and after: the scrim went from the viewport (1440x757) to the panel's own box
   (788x569). So the veil goes on a pseudo-element at `z-index:-1`, which blurs what is behind
   the panel while leaving `.chap` an ordinary containing block. IT IS THE HOUSE'S OWN ANSWER
   TOO: `sz-search-field` solves the identical problem with a `.veil` behind its pill. */
.chap::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;
  /* `--surface` AND NOT `--light`, MEASURED RATHER THAN CHOSEN BY NAME. In the dark theme
     `--light` resolves to #09090b, which is EXACTLY the body background: a 40% mix of the
     background over the background is the background, and the panel measured invisible on the
     rendered pixels (inside 9,9,10 against outside 9,9,11: a delta of zero). Blur cannot
     rescue it either, because a backdrop filter over a flat surface has nothing to blur: THE
     FILL IS WHAT MAKES A PANEL EXIST and the blur is only its texture. `--surface` is #18181b,
     the house's own raised colour, the one `sz-search-field` puts behind its pill. */
  /* THE FILL AND THE BLUR NOW COME FROM THE TOKENS, not from this copy. The values are
     identical -- this panel is where the recipe was measured -- but the truth moved to
     `tokens.css` so a skin redefines it once instead of every surface restating it. */
  background:var(--sz-glass-fill,color-mix(in srgb,var(--surface) 72%,transparent));
  /* NO BACKDROP FILTER, AND ITS REMOVAL IS A MEASUREMENT AND NOT A SIMPLIFICATION.
     This panel carried `blur(4px)` from the day it was built and the blur NEVER DID
     ANYTHING: there is nothing behind the panel but the flat page, and a backdrop filter
     over a flat surface has nothing to blur. Proven by photographing the page with and
     without the #stars canvas and differencing the frames: stars reach the inside of this
     panel at 18 per 10,000 pixels against the bare page's 19, and switching the blur to 0
     leaves it at 18. Identical. What makes this panel work is the 72% FILL letting the
     page through -- the blur was decoration on top of an effect it was not producing.
     And it was not free: the same diff reads ZERO stars inside every surface that had a
     LIVE blur, because a 4px blur spreads a 1px star until nothing survives. Blur belongs
     only where something actually passes behind -- the sticky search bar, a modal scrim. */
  pointer-events:none}
.chap .ico-col{grid-column:1;grid-row:1 / span 2;align-self:center;
  display:flex;align-items:center;justify-content:flex-start;padding-top:.15rem}
.chap .ico-col sz-icon,.chap .ico-col .ico{display:inline-flex}
.chap .ico-col .ico svg{width:36px;height:36px}
.chap > h2{grid-column:2;grid-row:1;padding-left:0;margin:0}
/* 2px, RULED ON THE RENDERED PAGE BY @rames ("titulo e sub titulo dos itens ainda muito
   grande... deixe em 2px"), and the source had LOST it. The grid is `gap:0 0`, so
   `margin:0` here is a 0px gap, not a small one. The value survived only inside a page's
   inline block; @dev-co found the divergence while mirroring and refused to guess which
   side was right, which is the correct call: a ruled value that lives in one page and not
   in the stylesheet is a value that disappears the moment that page is cleaned up. */
.chap > h3.sub{grid-column:2;grid-row:2;padding-left:0;margin:2px 0 0}
.chap > *:not(.ico-col):not(h2):not(h3.sub){grid-column:1 / -1}
/* THE SPACE BELONGS TO THE FIRST PROSE PARAGRAPH, AND `:first-of-type` GAVE IT TO THE SUBTITLE.
   The first `<p>` inside a panel is `p.sub`, so this rule matched the subtitle instead of the
   prose: same specificity as the `.sub` rule and later in the block, so it won, and the
   subtitle inherited a 16px top margin nobody wrote for it. @rames spotted it on the rendered
   page before any probe did. Targeting the paragraph that FOLLOWS the subtitle says what was
   meant and cannot drift onto a sibling again. */
.chap > h3.sub + p{margin-top:1rem}
.chap > *:last-child{margin-bottom:0}
/* the figure is an object inside the panel, never a second surface */
.chap .viz{background:transparent;backdrop-filter:none;-webkit-backdrop-filter:none;
  border-color:color-mix(in srgb,var(--lightgray) 65%,transparent)}
/* ============================================================================
   HINT TEXT ON A TERM, AND THE RULE IT KEEPS: THE HOVER IS NEVER THE ONLY COPY.

   @copy-chief's rule applied literally: the explanation lives in the SENTENCE, where all three
   readers reach it (the person, the buyer's research agent, our agent reading the .md). The
   attribute is the SHORT FORM of that same sentence, so the hover adds convenience and never
   carries meaning the prose lacks. His measured reason is this page's own defect: the
   aria-label versus <text> divergence came from two copies of the same words in two encodings,
   and only one of them ever got translated.

   NO SCRIPT. Hover, keyboard focus and tap all resolve through :hover and :focus-visible, so
   there is nothing to upgrade, nothing that can trap focus, and it works before any module
   loads. `tabindex=0` makes the term reachable by keyboard and gives a tap somewhere to land.
   The term is marked as a TERM and not as a link: dotted underline, body colour, no pointer,
   because the page carries four real links and a fifth affordance that looked the same
   would lie.
   ============================================================================ */
dfn[data-hint]{font-style:italic;position:relative;border-bottom:1px dotted var(--gray);
  cursor:help;outline:none}
dfn[data-hint]::after{content:attr(data-hint);position:absolute;left:0;top:calc(100% + .5rem);
  z-index:30;width:min(30rem,72vw);padding:.7rem .85rem;border:1px solid var(--lightgray);
  border-radius:10px;background:var(--light);color:var(--darkgray);
  font-style:normal;font-size:var(--fs-xs,.76rem);line-height:1.45;letter-spacing:0;
  box-shadow:0 8px 24px rgb(0 0 0 / .28);opacity:0;visibility:hidden;transition:opacity .12s ease}
dfn[data-hint]:hover::after,dfn[data-hint]:focus-visible::after{opacity:1;visibility:visible}
dfn[data-hint]:focus-visible{border-bottom-color:var(--secondary)}
/* THE SUBTITLE, ONE DEFINITION. It was written for a `<p class="sub">` sitting loose under an
   h2, with a 3.4rem indent and a negative top margin to pull it up: that context does not exist
   in this vocabulary, where the subtitle is a grid cell inside `.chap` and both values are
   overridden. Only the TYPOGRAPHY is shared, so only the typography lives here, and the two
   rules stopped describing two different worlds. Promoting `<p>` to `<h3>` was @sophia's SEO
   reading: the short-label H2s lost their keywords and the sentence carrying them had no
   heading weight. Every value below is the one the paragraph already had, so nothing moved. */
h3.sub{font-size:var(--fs-xs,.74rem);font-weight:var(--fw-normal,400);letter-spacing:.08em;text-transform:uppercase;color:var(--gray);line-height:1.15}
/* THE HEADING ANCHOR MUST NOT INFLATE THE LINE BOX, and this rule exists because promoting a
   subtitle to a heading is what introduces the problem. Quartz gives every heading an
   `a[role=anchor]` whose icon is 15px, inline, on the baseline: measured, an `h3` subtitle went
   to a 26px box for a 16px line, and the surplus reads as air nobody wrote. Capping it to the
   text's own em removes the inflation WITHOUT removing the anchor, so a heading keeps the link
   it earned by being a heading. Any page using `.chap` needs this; it is not a see.md fix. */
.chap h2 a[role=anchor],.chap h3.sub a[role=anchor]{
  display:inline-flex;align-items:center;height:1em;line-height:1;vertical-align:middle}

/* THE PIN, AND IT ORIGINATES NOTHING — which is the whole reason it took three measurements.
   My first draft wrote `font-size:12px` for the subtitle and `font-weight:600`. Both were wrong,
   and in the two ways this house keeps catching: `--fs-xs` IS 12px (`--sz-size-micro`, 6 × the
   2px ruler), so the literal restates a token and would have shown up in `skin_purity` as a
   number living nowhere; and 600 was a weight NOBODY measured — the rule above already carries
   `--fw-normal` and Copy Chief's reading named size, case and tracking, never weight. So the
   subtitle is not re-declared here at all: the rule above holds it, minus the `article` ancestor.

   WHAT IS PINNED IS THE H2, and only it, because it was the one value the panel borrowed from
   the HOST: each surface's `index.css` says `h2{font-size:1.4rem}` and the panel inherited it.
   1.4rem is 22.4px, which is what Copy Chief measured on both see.md and the mock — so nothing
   moves today; what changes is that it no longer DEPENDS on the host agreeing. And it is stated
   in rem rather than as a `--sz-u` multiple deliberately: 22.4px is not on the 2px ruler, and
   rounding it to 22 or 24 to make it fit would move a rendered value to flatter a grid. */
.chap > h2{font-size:1.4rem;line-height:1.25;font-weight:var(--fw-bold,700)}

/* THE DOCUMENT-ITEM ACCORDION (E4.3, ADR-047 Addendum 9, Rames's QA slide 15, 2026-09-17).
   Notes, comments and transcript open UNDER their unit and push what follows down; nothing floats
   over the slide. KEYED ON ATTRIBUTES ONLY, the seam Dev CO proposed on the sprint channel: the
   host sets data-accordion on .unit-body at mount (no-JS keeps the composer's hidden attribute, so
   the text stays in the served HTML for Quartz search) and toggles data-open on ONE section per
   unit plus aria-expanded on its tool. This file only moves pixels: without the attributes it is
   inert, and the attributes without it are a plain show/hide.
   HEIGHT EASES 0 TO AUTO THROUGH interpolate-size, NOT A GRID TRACK. The 0fr-to-1fr trick needs one
   child and a section holds whatever markdown the composer wrote (paragraphs, lists), so it would
   not close. Where interpolate-size is unsupported the section opens instantly, which is the
   reduced-motion behaviour anyway. Closed content is visibility:hidden so it takes no tab stop,
   and on close the visibility flip waits for the height to finish. */
.unit-body[data-accordion]{display:block}
.unit-body[data-accordion] > section{
  interpolate-size:allow-keywords;
  height:0;overflow:hidden;visibility:hidden;
  transition:height var(--dur-mid) var(--ease-out),visibility 0s linear var(--dur-mid)}
.unit-body[data-accordion] > section[data-open]{
  height:auto;visibility:visible;
  transition:height var(--dur-mid) var(--ease-out),visibility 0s}
@media (prefers-reduced-motion:reduce){
  .unit-body[data-accordion] > section,
  .unit-body[data-accordion] > section[data-open]{transition:none}
}
