/* ============================================================
   Episquire Design System — component layer
   EPQ-DS-000 · REV D · generated 2026-07-27
   Requires episquire.css (tokens, reset, theme scopes) loaded FIRST.

   One class per component in components/, matching the React source value for
   value. Every size is a type role and every surface is a semantic alias, so
   these work unchanged on the cyanotype ground.

   This layer was deliberately omitted from earlier exports because the site
   had its own equivalents under unprefixed names. It is included now so the
   export is complete: migrate a template by swapping its class names, or
   cherry-pick the components the site lacks. Do not run both layers over the
   same element.
   ============================================================ */

/* ---- Emphasis --------------------------------------------------------
   The UA default for <strong>/<b> is 700, which breaks the weight rule at
   every size under 34px — bold body copy at 21px closes its counters for no
   gain in authority. Emphasis inside body copy is --epq-w-label; anything at
   34px and up that wants 700 asks for it. */
strong, b { font-weight: var(--epq-w-label); }

/* ---- Wordmark -----------------------------------------------------------
   "EPISQUIRE" with the Q extending into a dimension line under QUIRE. The
   axis and ticks are em-based, so the mark scales from one font-size. */
.epq-wm {
  font-family: var(--epq-font-display);
  font-variation-settings: var(--epq-wm-vf);
  text-transform: uppercase;
  letter-spacing: var(--epq-track-wm);
  line-height: 1;
  display: inline-block;
  white-space: nowrap;
  text-decoration: none;
  color: inherit;
  font-size: 23px;
}
.epq-wm-axis { position: relative; padding-bottom: .16em; }
.epq-wm-axis::before,
.epq-wm-axis::after { content: ""; position: absolute; background: currentColor; }
.epq-wm-axis::before { left: 0; right: 0; bottom: 0; height: .055em; }
.epq-wm-axis::after { right: 0; bottom: 0; width: .055em; height: .20em; }
/* The left tick needs a third box; ::before/::after are spent on the rule and
   the right tick. An empty <i> inside .epq-wm-axis carries it. */
.epq-wm-axis > i { position: absolute; left: 0; bottom: 0; width: .055em; height: .20em; background: currentColor; }
/* Below ~120px wide drop the axis; below ~90px use the EPQ monogram instead. */

/* ---- Stamp — RETIRED in REV F ---------------------------------------
   The DOC / REV / FIELD / status placard is gone. Two reasons, and the second
   is the real one:
   ·  It read as interactive. Four bordered cells across the top of the page,
     one of them filled with the field colour, sitting exactly where a page's
     primary controls live. Users could not tell whether the cells were
     clickable, and nothing about them said either way.
   ·  It was decoration in a functional position. DOC and REV numbers are
     print-shop furniture: they carry the placard metaphor but nothing a
     visitor can act on. Occupying the top bar with them spends the most
     valuable strip on the page on atmosphere.
   The one live thing it carried — the status line — belongs in .epq-notice,
   which is a real persistent announcement. Use that.
   The document code itself still exists as a convention (EPQ-WEB-002.1–.4);
   put it in the footer, where furniture belongs. */

/* ---- Nav --------------------------------------------------------------- */
.epq-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 14px 28px;
  border-bottom: var(--epq-rule);
  flex-wrap: wrap;
}
.epq-nav ul {
  display: flex;
  gap: 20px;
  list-style: none;
  margin: 0;
  padding: 0;
  font-family: var(--epq-font-mono);
  font-size: var(--epq-t-control);
  font-weight: var(--epq-w-label);
  letter-spacing: var(--epq-track-label);
  text-transform: uppercase;
}
.epq-nav a {
  color: var(--epq-text);
  text-decoration: none;
  padding-bottom: 2px;
  border-bottom: 2px solid transparent;
}
.epq-nav a[aria-current="page"] { border-bottom-color: var(--epq-line); }
/* Hover underline is the field — one of the sanctioned interactive carries. */
.epq-nav a:hover { border-bottom-color: var(--epq-field); }

/* ---- Ink bar (marker) -------------------------------------------------
   Anything that paints itself on --epq-ink wears this. It carries the pairing
   (unrevealed ground, unrevealed text) and it is what theme.css keys the
   cyanotype substitution off, so a new ink bar cannot be missed. */
.epq-ink-bar { background: var(--epq-ink); color: var(--epq-src-vellum); }

/* ---- Clause — numbered section head -----------------------------------
   Ink bar, vellum text. The number is field-coloured: binding rule 3's
   primary carry, so the field recurs at every section head down the page.
   On the cyanotype ground episquire.css re-grounds this to the panel. */
.epq-clause-bar {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 16px 28px;
  border-bottom: var(--epq-hair);
  /* Unrevealed ground, so unrevealed text — see the note on .epq-notice. */
  background: var(--epq-ink);
  color: var(--epq-src-vellum);
}
.epq-clause-no {
  font-family: var(--epq-font-mono);
  font-size: var(--epq-t-clause);
  font-weight: var(--epq-w-label);
  color: var(--epq-field);
}
.epq-clause-bar h2 {
  font-family: var(--epq-font-display);
  font-variation-settings: var(--epq-clause-vf);
  /* Explicit: the UA gives h2 700, which the variable font's "wght" 600 masks
     only while Archivo is loaded — the fallback would render 700 at 21px. */
  font-weight: var(--epq-w-label);
  font-size: var(--epq-t-clause);
  letter-spacing: var(--epq-track-clause);
  text-transform: uppercase;
  margin: 0;
}

/* ---- Hero -------------------------------------------------------------- */
.epq-hero { display: grid; grid-template-columns: minmax(0, 1fr) 260px; border-bottom: var(--epq-rule); }
/* A container, so the H1 can size on the COLUMN rather than the viewport.
   --epq-t-display's 7.2vw assumes display text spans the full width; inside a
   hero it has viewport minus the 260px mark minus 56px padding, so a long word
   overflows at wide-but-not-huge widths. cqw removes the guesswork. */
.epq-hero-body { padding: 44px 28px 40px; min-width: 0; container-type: inline-size; }
.epq-eyebrow {
  font-family: var(--epq-font-mono);
  font-size: var(--epq-t-label);
  font-weight: var(--epq-w-label);
  letter-spacing: var(--epq-track-eyebrow);
  text-transform: uppercase;
  color: var(--epq-text-muted);
  margin: 0 0 16px;
}
.epq-hero h1 {
  font-family: var(--epq-font-display);
  font-variation-settings: var(--epq-display-vf);
  font-size: var(--epq-t-display);
  line-height: var(--epq-lh-display);
  letter-spacing: var(--epq-track-display);
  text-transform: uppercase;
  margin: 0 0 22px;
}
/* The lede is the middle step of the hierarchy — deliberately far from body
   size. Do not close this gap; a tagline near body size reads as body. */
.epq-lede { max-width: 40ch; font-size: var(--epq-t-lede); line-height: var(--epq-lh-lede); margin: 0; }
.epq-hero-mark {
  background: var(--epq-field);
  border-left: var(--epq-rule);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 22px;
}
@media (max-width: 740px) {
  .epq-hero { grid-template-columns: minmax(0, 1fr); }
  .epq-hero-mark { border-left: 0; border-top: var(--epq-rule); }
  .epq-hero-body { padding: 32px 16px 28px; }
}

/* ---- Button -----------------------------------------------------------
   Hover and active are real CSS states here (the React component drives them
   from JS because it merges inline styles). Stepped, never eased. */
.epq-btn {
  font-family: var(--epq-font-display);
  font-variation-settings: var(--epq-btn-vf);
  text-transform: uppercase;
  letter-spacing: var(--epq-track-label);
  font-size: var(--epq-t-control);
  padding: 16px 28px;
  min-height: 44px;
  border: var(--epq-rule);
  /* The CTA is a ROLE colour, not the view's field: the field identifies the
     view, this identifies the thing you can press. Exempt from
     one-field-per-view because it never varies per page. */
  background: var(--epq-cta);
  color: var(--epq-on-cta);
  box-shadow: 5px 5px 0 0 var(--epq-line);
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
  transition: var(--epq-press);
}
.epq-btn:hover { transform: translate(3px, 3px); box-shadow: 2px 2px 0 0 var(--epq-line); }
.epq-btn:active { transform: translate(5px, 5px); box-shadow: 0 0 0 0 var(--epq-line); }
/* Neutral variants follow the view's text colour so they survive the ground. */
.epq-btn-sec { background: var(--epq-surface-card); color: var(--epq-text); }
.epq-btn-ghost { background: transparent; color: var(--epq-text); }
.epq-btn:focus-visible { outline: 3px solid var(--epq-focus-ring); outline-offset: 2px; }
/* The form posts with fetch, so the button needs a pending state the system
   never had. cursor:progress rather than not-allowed — it is working, not
   refusing. */
.epq-btn[disabled] { opacity: .5; cursor: progress; }

/* ---- Input ------------------------------------------------------------- */
.epq-input { border: var(--epq-rule); background: var(--epq-surface-card); }
.epq-input label {
  display: block;
  font-family: var(--epq-font-mono);
  font-size: var(--epq-t-label);
  font-weight: var(--epq-w-label);
  letter-spacing: var(--epq-track-label);
  text-transform: uppercase;
  padding: 7px 11px;
  border-bottom: var(--epq-hair);
  background: var(--epq-surface-page);
  color: var(--epq-text);
}
.epq-input input,
.epq-input textarea {
  width: 100%;
  border: 0;
  background: transparent;
  padding: 15px 13px;
  font-family: var(--epq-font-mono);
  font-size: var(--epq-t-control);
  color: var(--epq-text);
  outline: none;
}
/* Inset so the ring cannot be clipped by the 2px container rule. */
.epq-input input:focus,
.epq-input textarea:focus { outline: 3px solid var(--epq-focus-ring); outline-offset: -3px; }

/* ---- Tag --------------------------------------------------------------
   State fills are semantic signals, exempt from one-field-per-view. Ink on a
   pigment fill in both themes; the two neutral fills follow the view. */
.epq-tag {
  font-family: var(--epq-font-mono);
  font-size: var(--epq-t-label);
  font-weight: var(--epq-w-label);
  letter-spacing: var(--epq-track-label);
  text-transform: uppercase;
  padding: 3px 8px;
  border: var(--epq-hair);
  background: var(--epq-surface-card);
  color: var(--epq-text);
  white-space: nowrap;
  display: inline-block;
}
.epq-tag-pending { background: var(--epq-surface-page); color: var(--epq-text); }
/* Foregrounds come from --epq-on-f-*, which flip with the theme. Hardcoding
   #fff on drift and agents was theme-blind: the -rev fills are lighter, so
   white fell to 3.1:1 and 3.5:1 on the ground. */
.epq-tag-verify { background: var(--epq-f-verify); color: var(--epq-on-f-verify); }
.epq-tag-capture { background: var(--epq-f-capture); color: var(--epq-on-f-capture); }
.epq-tag-explorer { background: var(--epq-f-explorer); color: var(--epq-on-f-explorer); }
.epq-tag-agents { background: var(--epq-f-agents); color: var(--epq-on-f-agents); }
.epq-tag-drift { background: var(--epq-f-drift); color: var(--epq-on-f-drift); }

/* ---- DataTable --------------------------------------------------------
   "Chrome is loud, data is quiet": 2px outer rule, 1px cells, mono headers,
   tabular numerals so columns of figures align. */
.epq-table {
  width: 100%;
  border-collapse: collapse;
  border: var(--epq-rule);
  background: var(--epq-surface-card);
  color: var(--epq-text);
}
.epq-table th {
  text-align: left;
  padding: 8px 12px;
  border-bottom: var(--epq-rule);
  border-right: var(--epq-hair);
  background: var(--epq-surface-page);
  font-family: var(--epq-font-mono);
  font-size: var(--epq-t-label);
  font-weight: var(--epq-w-label);
  letter-spacing: var(--epq-track-label);
  text-transform: uppercase;
}
.epq-table td {
  padding: 10px 12px;
  border-bottom: var(--epq-hair);
  border-right: var(--epq-hair);
  font-family: var(--epq-font-mono);
  font-size: var(--epq-t-detail);
  font-variant-numeric: tabular-nums;
}
.epq-table th:last-child,
.epq-table td:last-child { border-right: 0; }

/* ---- Roundel ----------------------------------------------------------
   The only mark in the system besides the wordmark — an inline SVG with mono
   type on a circular path. It has no CSS surface; see components/brand/
   Roundel.jsx for the geometry and copy it as SVG.
   Ring type is 8.4px in the source and is intentionally exempt from the 13px
   floor: it is a mark, not text, and carries no information the page needs. */


/* ==========================================================================
   ABSORBED FROM EPISQUIRE WEB, 2026-07-27 (upstream §7)
   Nine patterns the site built that REV C had no entry for. Renamed to the
   .epq- prefix and re-sized to the type roles — nothing below the 13px floor
   survived (the originals ran 9.5–13.5px). Each note is the reason the
   component exists, so each note is kept.
   ========================================================================== */

/* ---- Price pair --------------------------------------------------------
   Two prices, always, side by side: standard struck through beside the
   early-bird figure on a field-coloured chip. The SAVING is the argument, so
   publishing one half alone is forbidden — the site's build refuses to ship
   one without the other, and that check belongs with the component, not the
   page. */
.epq-price { display: flex; flex-wrap: wrap; gap: 0 22px; padding-top: 14px; border-top: var(--epq-hair); }
.epq-price > div { display: flex; flex-direction: column; gap: 3px; }
.epq-price span { font-family: var(--epq-font-mono); font-size: var(--epq-t-label); letter-spacing: var(--epq-track-label); text-transform: uppercase; color: var(--epq-text-muted); }
.epq-price b { font-family: var(--epq-font-display); font-variation-settings: "wdth" 106, "wght" 800; font-size: var(--epq-t-title); font-weight: var(--epq-w-title); letter-spacing: -.01em; font-variant-numeric: tabular-nums; }
.epq-price > div:first-child b { color: var(--epq-text-muted); text-decoration: line-through; text-decoration-thickness: 2px; }
.epq-price-early b { background: var(--epq-field); color: var(--epq-on-field); padding: 1px 7px; }

/* ---- Notice band ------------------------------------------------------
   A persistent announcement directly under the hero. Ink ground, vellum type —
   NOT the field: the field belongs to the hero block above it, and two
   field-coloured slabs stacked read as one. On the cyanotype ground it becomes
   the raised panel, like every other ink bar (see theme.css). */
/* Ground is --epq-ink, which the reveal deliberately never touches, so the
   text must be unrevealed too: --epq-vellum mixes to the exposure colour and
   converged with the ink ground for the whole hold. A foreground and its
   background must sit on the same side of the reveal.
   Carries .epq-ink-bar in markup — that marker is what earns the cyanotype
   treatment in theme.css. An ink bar without it stays a black slab on the
   ground, which is the bug this class had. */
.epq-notice { background: var(--epq-ink); color: var(--epq-src-vellum); padding: 11px 28px; border-bottom: var(--epq-rule); font-family: var(--epq-font-mono); font-size: var(--epq-t-label); font-weight: var(--epq-w-label); letter-spacing: var(--epq-track-label); text-transform: uppercase; }

/* ---- Detail link ------------------------------------------------------
   The secondary action beside a CTA: mono uppercase on a 2px field underline
   that swaps to line colour on hover — the nav's hover gesture run in reverse,
   which is what keeps it reading as navigation rather than a second button.
   Always a real anchor; never a JS-only handler. */
.epq-det-link { font-family: var(--epq-font-mono); font-size: var(--epq-t-label); font-weight: var(--epq-w-label); letter-spacing: var(--epq-track-label); text-transform: uppercase; color: var(--epq-text); text-decoration: none; border-bottom: 2px solid var(--epq-field); padding-bottom: 2px; }
.epq-det-link:hover, .epq-det-link:focus-visible { border-bottom-color: var(--epq-line); }
.epq-det-link:focus-visible { outline: 3px solid var(--epq-focus-ring); outline-offset: 3px; }

/* ---- Footnote rule ----------------------------------------------------
   A quiet qualifier under body copy: structural rule on the left edge, no
   fill, no icon. It gets no button and no link — if it needs an action it is
   not a footnote. */
.epq-footnote { font-size: var(--epq-t-detail); color: var(--epq-text-muted); border-left: var(--epq-rule); padding-left: 12px; max-width: 56ch; }

/* ---- Card group grid --------------------------------------------------
   Cards are grouped by the problem they answer and each group owns its own
   grid: two columns for a group of two, full width for a group of one — a lone
   card in a 2-col track reads as a missing sibling. Deliberately NOT one grid
   across every card; a single 2x2 block reads as tiers of one product. */
.epq-group { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); border: var(--epq-rule); border-bottom: 0; }
.epq-group-one { grid-template-columns: minmax(0, 1fr); }
.epq-group > :nth-child(2n), .epq-group-one > * { border-right: 0; }
@media (max-width: 740px) { .epq-group { grid-template-columns: minmax(0, 1fr); } .epq-group > * { border-right: 0; } }

/* ---- Label / answer list ----------------------------------------------
   A <dl> where each answer is a commitment with a consequence. Hairline
   between pairs, Archivo term, no bullets — bullets flatten a commitment into
   a feature. */
.epq-dl { margin: 0 0 30px; display: grid; gap: 0; border-top: var(--epq-hair); }
.epq-dl dt { font-family: var(--epq-font-display); font-variation-settings: "wdth" 106, "wght" 700; font-size: var(--epq-t-body); text-transform: uppercase; letter-spacing: .02em; padding: 16px 0 6px; }
.epq-dl dd { margin: 0 0 16px; font-size: var(--epq-t-body); line-height: 1.65; max-width: 64ch; border-bottom: var(--epq-hair); padding-bottom: 16px; }
.epq-dl dd:last-child { border-bottom: 0; }

/* ---- Numbered block --------------------------------------------------
   The body unit below Clause in the hierarchy: clause bars are ink-filled and
   per-section, these are per sub-section and carry no fill. Numbers are
   DERIVED from position, never authored, so a block inserted mid-page cannot
   desynchronise the sequence — hence the CSS counter rather than markup. */
.epq-blocks { counter-reset: epq-blk; }
.epq-block { border-top: var(--epq-hair); padding-top: 20px; margin-bottom: 26px; counter-increment: epq-blk; }
.epq-block:first-child { border-top: 0; padding-top: 0; }
.epq-block:last-child { margin-bottom: 0; }
.epq-block-hd { display: flex; align-items: baseline; gap: 12px; margin: 0 0 12px; }
.epq-block-hd::before { content: counter(epq-blk, decimal-leading-zero); font-family: var(--epq-font-mono); font-size: var(--epq-t-label); font-weight: var(--epq-w-label); color: var(--epq-text-muted); }
.epq-block p { margin: 0 0 12px; font-size: var(--epq-t-body); line-height: 1.65; max-width: 64ch; }
.epq-block ul, .epq-block ol { margin: 0 0 12px; padding-left: 20px; max-width: 64ch; font-size: var(--epq-t-body); line-height: 1.7; }
.epq-block li b { font-family: var(--epq-font-display); font-variation-settings: "wdth" 104, "wght" 700; }

/* ---- Two panel weights ------------------------------------------------
   Vellum = an offer (something you can buy). Manila = a limit (what we do not
   do). Same 2px rule, same square corners; the ground is the whole signal, and
   it is the one place the substrate pair carries meaning rather than depth.
   Semantic aliases, so the pair still reads as two weights on the ground. */
.epq-offer { border: var(--epq-rule); background: var(--epq-surface-card); padding: 22px 24px; max-width: 70ch; }
.epq-limit { border: var(--epq-rule); background: var(--epq-surface-page); padding: 20px 22px; max-width: 70ch; }

/* ---- Form acknowledgement --------------------------------------------
   Reserves its own height before it has content, so nothing below it moves
   when it fills, and grows a structural left rule only once it says something.
   At the label floor: this carries RECORDED / REJECTED, which is the outcome
   the visitor is waiting for. */
.epq-ack { font-family: var(--epq-font-mono); font-size: var(--epq-t-label); line-height: 1.7; letter-spacing: .04em; margin-top: 18px; min-height: 1.4em; max-width: 56ch; }
.epq-ack-on { border-left: var(--epq-rule); padding-left: 12px; }

/* ---- Figure play control (upstream §3/§4) -----------------------------
   Ambient motion, stepped like everything else: hold out, hard-cut to a 2px
   depress, hold, hard-cut back. Transform and shadow move together so the far
   edge stays put and it reads as a press, not a drift. Stops on hover, focus
   and press — once the reader is on the control the attractor has done its job
   and would only fight the real press for the same two properties.
   Positioned over the figure but a SIBLING of it in the DOM: the bands are
   role="img", and a focusable control inside an image role is either
   unreachable or nonsense depending on the reader. */
.epq-fig-ctl { position: absolute; top: 14px; right: 14px; z-index: 5; }
/* The original scaled type and box together off a --s knob. Written out here
   instead: a local custom property on a component class is not a design token,
   and there are only two sizes. */
.epq-fig-play { display: inline-flex; align-items: center; font-family: var(--epq-font-mono); font-size: var(--epq-t-label); font-weight: var(--epq-w-label); letter-spacing: var(--epq-track-label); text-transform: uppercase; padding: 11px 16px; min-height: 44px; border: var(--epq-rule); background: var(--epq-cta); color: var(--epq-on-cta); box-shadow: 5px 5px 0 0 var(--epq-line); cursor: pointer; transition: var(--epq-press); animation: epq-breathe var(--epq-breathe) steps(1) infinite; }
.epq-fig-play:hover { transform: translate(3px, 3px); box-shadow: 2px 2px 0 0 var(--epq-line); animation: none; }
.epq-fig-play:active { transform: translate(5px, 5px); box-shadow: 0 0 0 0 var(--epq-line); animation: none; }
.epq-fig-play:focus-visible { outline: 3px solid var(--epq-focus-ring); outline-offset: 3px; animation: none; }
/* Paired stops, so the value is constant across each hold and the only
   movement is the cut between them. steps(1) makes those two cuts hard. */
@keyframes epq-breathe {
  0%, 46% { transform: translate(0, 0); box-shadow: 5px 5px 0 0 var(--epq-line); }
  50%, 96% { transform: translate(2px, 2px); box-shadow: 3px 3px 0 0 var(--epq-line); }
  100% { transform: translate(0, 0); box-shadow: 5px 5px 0 0 var(--epq-line); }
}
/* Reduced motion kills every animation, so the figure cannot play and the
   control would do nothing. A button that does nothing is worse than no
   button — and the figure rests on its finished frame there, which is the
   state the button existed to reach. */
@media (prefers-reduced-motion: reduce) { .epq-fig-ctl { display: none; } }
/* Narrow figures: tighter inset and padding. The type does NOT shrink — it is
   already at the 13px floor. */
@container (max-width: 560px) { .epq-fig-ctl { top: 10px; right: 10px; } .epq-fig-play { padding: 10px 13px; } }
