/* ===========================================================================
   tool-chassis.css — the shared chassis every Coastal SD Pros tool is built on.

   READ THIS BLOCK. It is the whole contract. Eight tools are being built in
   parallel against this file; if you invent a class instead of using one below,
   the tools stop looking like one product and the directory stops looking like
   it has evidentiary discipline.

   Load order on a tool page:
       <link rel="stylesheet" href="/assets/tool-chassis.css">
       <script src="/assets/tool-chassis.js" defer></script>
   and, in <head>, before any stylesheet, the no-flash JS flag:
       <script>document.documentElement.classList.add('js');</script>

   This file is standalone. It mirrors the ten canon palette tokens itself
   (see the :root block immediately below), so it does not require v4.css.
   Loading it next to v4.css is safe — same names, same values.

   ---------------------------------------------------------------------------
   1. SHELL — the six regions every tool has, in this DOM order
   ---------------------------------------------------------------------------
   .tc-tool              Root of one tool. Sets the corrected focus ring for
                         everything inside. Use <section class="tc-tool"
                         aria-labelledby="ID-title">.
   .tc-tool__head        Region 1+2+3: title, purpose, method disclosure.
                         Emitted by _partials/tool-shell.html — do not hand-write.
   .tc-tool__title       Region 1. The tool name. <h2>. id="ID-title".
   .tc-tool__purpose     Region 2. ONE sentence: what the tool does. No claims.
   .tc-method            Region 3. <details> method disclosure. Closed by
                         default, fully readable with JS off.
   .tc-method__summary   "How this works, and what it does not tell you"
   .tc-method__body      Wrapper for the disclosure content.
   .tc-method__h         <h3> inside the disclosure.
   .tc-method__p         Paragraph inside the disclosure.
   .tc-input             Region 4. The input region. Normally a <form>.
   .tc-input__legend     Optional heading for the input region.
   .tc-result            Region 5. The result region. Holds .tc-field / .tc-held.
                         Do NOT put aria-live on it — announce via .tc-live.
   .tc-result__head      Optional heading row inside the result region.
   .tc-foot              Region 6. Source + checked-date footer. REQUIRED on
                         every tool, even a tool whose output is held.
   .tc-foot__label       "Sources" label.
   .tc-foot__list        <ul> of sources. .tc-foot__item per source.
   .tc-foot__item        One source line — carries a .tc-chip.

   ---------------------------------------------------------------------------
   2. PROVENANCE CHIP — source name + checked date, travelling with the value
   ---------------------------------------------------------------------------
   .tc-chip              "SOURCE NAME · checked DATE". A SINGLE text node —
                         children become extra flex items and add a phantom gap.
                         Put one next to every fact, every blank, every source.
   .tc-chip--held        Same chip, sand ground. For a line where the source and
                         date are known but the value is not on hand.

   Compatibility: `.tc-tool .stamp--chip` is styled identically, so the existing
   _partials/provenance-chip.html stamps into a tool unchanged and renders the
   same as .tc-chip. Either is correct; the stamped partial is preferred because
   it cannot drift.

   The chip's leading dot is a DOT, deliberately not a checkmark. A checkmark
   reads as "verified". This site does not verify anyone. Do not change it.

   ---------------------------------------------------------------------------
   3. FACTS + THE HONEST BLANK
   ---------------------------------------------------------------------------
   .tc-field             One fact: label, value, chip. The only fact container.
   .tc-field__label      What the fact is ("License status").
   .tc-field__value      The value. Only ever a real, sourced value.
   .tc-field__note       Plain-language caveat that must travel WITH the value.
                         Mandatory sentence for workers' comp, verbatim:
                         "Workers' compensation is not general liability
                          insurance. This line says nothing about whether this
                          business carries general liability cover."
   .tc-field--blank      THE HONEST BLANK. Same box, same padding, same type
                         size and weight as a populated field. It is a result,
                         not an apology. Never dim it, never italicise it,
                         never add opacity. (.tc-field__state shares its entire
                         declaration with .tc-field__value so the two cannot
                         drift apart. Keep it that way.)
   .tc-field__state      The blank's value slot: "Not published", "Not on the
                         record". Written as a fact about the record.
   .tc-field__where      Where the homeowner checks instead, with a real link.

   ---------------------------------------------------------------------------
   4. HELD OUTPUT — for a tool whose method ran but whose input is missing
   ---------------------------------------------------------------------------
   .tc-held              Gated result. Shows the method ran; names the missing
                         input and who supplies it; shows NO number, no range,
                         no estimate, no progress bar. If you are tempted to
                         render "approximately", you are rendering an invention.
   .tc-held__title       "The method ran. The output is held."
   .tc-held__ran         <ol> of the steps that actually executed.
   .tc-held__missing     What input is missing, in plain words.
   .tc-held__who         Who supplies it and how it arrives.
   .tc-held__rule        Coral marker bar. Decoration only — the words carry
                         the meaning. Coral is capped at 2% of the page.

   ---------------------------------------------------------------------------
   5. FORM PRIMITIVES — native controls, 44px targets, plain-language errors
   ---------------------------------------------------------------------------
   .tc-form              Grid wrapper inside .tc-input.
   .tc-control           One labelled control. Wraps label + hint + field + error.
   .tc-label             <label for="ID">. Every control has a real label; an
                         unlabelled control is a build failure, not a style choice.
   .tc-hint              Help text. id="ID-hint", referenced by aria-describedby.
   .tc-select            Native <select>. No custom dropdown, ever.
   .tc-text              Native <input> / <textarea>.
   .tc-error             Inline validation message. id="ID-error", role="alert",
                         starts with the `hidden` attribute. tool-chassis.js
                         wires it into aria-describedby when it fires.
                         Error TEXT is Pacific 900, not coral — coral on foam is
                         2.53:1 and fails. Coral appears only as the marker bar.
   .tc-actions           Row of buttons.
   .tc-btn               Base button. 44px minimum target.
   .tc-btn--primary      Pacific 900 ground, white text (11.7:1). Ocean 600
                         ground would be 4.18:1 and fails normal-size text —
                         do not "brighten" this.
   .tc-btn--quiet        White ground, Pacific 900 text, Ocean 600 border.

   ---------------------------------------------------------------------------
   6. STATUS, LIVE REGION, NO-JS
   ---------------------------------------------------------------------------
   .tc-live              Visually hidden polite live region. Exactly one per
                         tool: <p class="tc-live" data-tc-live role="status"
                         aria-live="polite" aria-atomic="true"></p>.
                         Announce through CSDPChassis.announce(), never by
                         writing innerHTML into it directly.
   .tc-status            Visible status line. Always says in words what state
                         the tool is in. Motion never carries the meaning.
   .tc-status--busy      Adds a pulse. The word "Checking…" must still be there.
   .tc-nojs              No-JS fallback notice. Hidden when <html> has .js.
                         Every tool needs one, and the result region must be
                         readable with JS off.
   [data-tc-js-only]     Hidden when <html> lacks .js.
   .tc-sr                Screen-reader-only text.

   ---------------------------------------------------------------------------
   7. RULES THIS FILE ENCODES (do not undo them in a tool stylesheet)
   ---------------------------------------------------------------------------
   - Focus ring is a 3px Pacific 900 outline with an Aqua 400 halo. The old
     3px Aqua-on-Foam ring is 1.61:1 and fails. The halo is decorative; the
     Pacific ring carries the 11:1 contrast. Do not swap them back.
   - Structural borders use Ocean 600 (4.18:1 on white). Sky 400 is 2.23:1 and
     is only ever a decorative divider, never the edge of a control.
   - Minimum touch target is 44px on every control and button.
   - No composite score, verdict, badge, seal, star, meter or progress bar has
     a class here. That is deliberate. Do not add one.
   - prefers-reduced-motion removes every transition, animation and smooth
     scroll while leaving all text, states and structure intact.

   ---------------------------------------------------------------------------
   8. HOW TO ASSEMBLE ONE TOOL — copy this skeleton
   ---------------------------------------------------------------------------
   Regions 1-3 are STAMPED, not hand-written. `_partials/tool-shell.html` emits
   the head; run `node scripts/stamp-partials.mjs --write` from site-elite/.
   Its five keys are id, title, purpose, method, limits — all five required,
   all five plain text (values are HTML-escaped, markup is not possible).
   Region 6 reuses the existing `_partials/provenance-chip.html`.
   A partial cannot wrap hand-written markup, which is why the head and the
   footer are two stamped blocks with your tool's own markup between them.

   The marker pair is an HTML comment on its own line, exactly:
       <!-- csdp:include tool-shell {"id":"license","title":"...","purpose":"...",
            "method":"...","limits":"..."} -->     (one line, no wrapping)
       <!-- /csdp:include tool-shell -->

   <section class="tc-tool" aria-labelledby="license-title">
     <!-- csdp:include tool-shell {"id":"license", ...five keys...} -->
       ... stamped .tc-tool__head — do not hand-edit, the stamper overwrites it ...
     <!-- /csdp:include tool-shell -->

     <p class="tc-nojs">This tool needs JavaScript to run the check. The
        sources and dates below are readable either way.</p>

     <form class="tc-input" data-tc-form>
       <p class="tc-input__legend">What you have</p>
       <div class="tc-form">
         <div class="tc-control">
           <label class="tc-label" for="license-number">CSLB licence number</label>
           <p class="tc-hint" id="license-number-hint">Eight digits, from the
              contractor's van, card or bid.</p>
           <input class="tc-text" id="license-number" name="license-number"
                  aria-describedby="license-number-hint" required>
           <p class="tc-error" id="license-number-error" role="alert" hidden></p>
         </div>
       </div>
       <div class="tc-actions">
         <button class="tc-btn tc-btn--primary" type="submit">Check the record</button>
       </div>
     </form>

     <p class="tc-status">Nothing checked yet.</p>
     <p class="tc-live" data-tc-live role="status" aria-live="polite" aria-atomic="true"></p>

     <div class="tc-result">
       ... .tc-field / .tc-field--blank / .tc-held ...
     </div>

     <footer class="tc-foot">
       <p class="tc-foot__label">Sources</p>
       <ul class="tc-foot__list">
         <li class="tc-foot__item">
           <!-- csdp:include provenance-chip {"source":"...","checked":"..."} -->
             ... stamped chip ...
           <!-- /csdp:include provenance-chip -->
         </li>
       </ul>
     </footer>
   </section>
   =========================================================================== */

:root {
  /* ------------------------------------------------------------------
     CANON PALETTE — RE-POINTED TO THE DIRECTORY SYSTEM (2026-07-26).
     Still byte-identical to the v4.css canon block; both were re-pointed
     together, so that invariant holds.

     The original ten values came from
     CSDP-CARTOON-ANIMATION-COMPONENT-SYSTEM-2026-07-23.md, the cartoon
     direction superseded by the owner's 2026-07-22 light-Apple-minimal lock.

     Why: every tool page and every city hub loads this file and NOT
     directory.css, so the whole tools section — the part of the site that is
     actually the differentiator — rendered on a #F4FBFF blue ground with
     #07366F headings and a #F5E4BD sand surface, while the 252 directory
     pages rendered white / #17202a / #147d80. Two design systems, one
     domain. Re-pointing these values converges them without touching markup.
     ------------------------------------------------------------------ */
  --pacific-900: #17202a; /* ink — headings, body text, contours */
  --pacific-700: #5f6368; /* muted — secondary text and quiet surfaces */
  --ocean-600: #147d80;   /* teal — primary action */
  --sky-400: #d8d9dc;     /* hairline — interface faces and rules */
  --aqua-400: #147d80;    /* teal — live state */
  --foam-50: #ffffff;     /* page ground — white, as the directory */
  --foam-100: #f7f6f2;    /* paper — quiet sections */
  --sand-200: #f3f4f5;    /* neutral band — the held/blank surface */
  --sun-300: #d95745;     /* coral — attention cue */
  --coral-400: #d95745;   /* coral — error cue */

  /* Pure white is a neutral card face, not a palette hue. */
  --tc-white: #FFFFFF;

  /* Neutral ink shadow — the blue-tinted original read as a different brand. */
  --tc-shadow: 0 8px 22px rgba(23, 32, 42, .08);
  --tc-shadow-soft: none;

  /* Interface typeface. Apple platforms take their own system face first; every
     other platform takes self-hosted Inter (declared below). Arial sits last as
     a true last resort, never as the second choice. Matches --dir-sans. */
  --tc-sans: -apple-system, BlinkMacSystemFont, Inter, "Segoe UI", Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif;
}

.csdp-brand__accent {
  color: var(--sun-300);
}

/* Same variable file as directory.css. Declared here so tool and registry pages
   that never load directory.css still get a real typeface. Deduped by URL. */
@font-face {
  font-family: Inter;
  src: url("/assets/fonts/inter-var-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   Derived tokens. Everything below this line resolves through var().
   -------------------------------------------------------------------------- */
.tc-tool {
  --tc-ink: var(--pacific-900);
  --tc-ink-soft: var(--pacific-700);
  --tc-surface: var(--tc-white);
  --tc-ground: var(--foam-50);
  --tc-quiet: var(--foam-100);
  --tc-warm: var(--sand-200);
  --tc-cue: var(--sun-300);
  --tc-live: var(--aqua-400);
  --tc-alert: var(--coral-400);

  /* Ocean 600 = 4.18:1 on white: legal for a control edge. */
  --tc-edge: var(--sky-400);
  /* Sky 400 = 2.23:1 on white: decorative dividers only. */
  --tc-divider: var(--sky-400);

  --tc-focus-ring: var(--sun-300);
  --tc-focus-halo: transparent;

  --tc-radius-sm: 8px;
  --tc-radius-md: 8px;
  --tc-radius-lg: 8px;
  --tc-tap: 44px;

  /* Motion contract, section 9: control 140-220ms, panel 280-360ms,
     entrance 420-600ms. */
  --tc-t-control: 180ms;
  --tc-t-panel: 320ms;
  --tc-t-enter: 480ms;
  --tc-ease: cubic-bezier(.2, .7, .3, 1);

  position: relative;
  display: grid;
  gap: 20px;
  padding: clamp(20px, 3vw, 32px);
  color: var(--tc-ink);
  background: var(--tc-surface);
  border: 1px solid var(--tc-divider);
  border-radius: var(--tc-radius-lg);
  box-shadow: var(--tc-shadow-soft);
  font-family: var(--tc-sans);
  font-size: 16px;
  line-height: 1.55;
}

.tc-tool *,
.tc-tool *::before,
.tc-tool *::after {
  box-sizing: border-box;
}

/* Any author `display` beats the UA stylesheet's `[hidden] { display: none }`.
   Every component here sets display, so without this rule a .tc-error with the
   `hidden` attribute keeps rendering — an empty error slot with a coral bar
   under every field, forever. Caught in the browser, not by reading the file.
   v4.css and tools.css already do this globally; the chassis restores it too so
   it stays correct standalone. */
.tc-tool [hidden],
.tc-tool[hidden] {
  display: none !important;
}

/* --------------------------------------------------------------------------
   THE CORRECTED FOCUS RING
   Pacific 900 outline (11.06:1 on Foam 50) with an Aqua 400 halo so the ring
   also reads against deep Pacific surfaces. Specificity (0,2,0) so it beats
   the site-wide (0,1,0) `:focus-visible` in v4.css and tools.css whatever the
   load order is. The halo is a box-shadow spread of 8px; the 3px outline sits
   at offset 2px, so the eye sees aqua / pacific / aqua.
   -------------------------------------------------------------------------- */
.tc-tool :focus-visible,
.tc-tool:focus-visible {
  outline: 3px solid var(--tc-focus-ring);
  outline-offset: 2px;
  box-shadow: none;
  border-radius: var(--tc-radius-sm);
}

/* Never remove the ring for mouse users only to lose it for keyboard users. */
.tc-tool :focus:not(:focus-visible) {
  outline: none;
}

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

/* ==========================================================================
   1. SHELL
   ========================================================================== */

.tc-tool__head {
  display: grid;
  gap: 12px;
}

.tc-tool__title {
  margin: 0;
  font-size: clamp(22px, 2.4vw, 30px);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -.01em;
  color: var(--tc-ink);
  text-wrap: balance;
}

.tc-tool__purpose {
  margin: 0;
  max-width: 62ch;
  font-size: 17px;
  color: var(--tc-ink-soft);
  text-wrap: pretty;
}

/* --- Method disclosure ---------------------------------------------------- */

.tc-method {
  border: 1px solid var(--tc-edge);
  border-radius: var(--tc-radius-md);
  background: var(--tc-quiet);
}

.tc-method__summary {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: var(--tc-tap);
  padding: 10px 16px;
  font-weight: 600;
  color: var(--tc-ink);
  cursor: pointer;
  list-style: none;
  border-radius: var(--tc-radius-md);
}

.tc-method__summary::-webkit-details-marker {
  display: none;
}

.tc-method__summary::before {
  content: "";
  flex: none;
  width: 9px;
  height: 9px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  transition: transform var(--tc-t-control) var(--tc-ease);
}

.tc-method[open] > .tc-method__summary::before {
  transform: rotate(45deg);
}

.tc-method__summary:hover {
  background: var(--tc-warm);
}

.tc-method__body {
  display: grid;
  gap: 8px;
  padding: 4px 16px 18px;
  border-top: 1px solid var(--tc-divider);
  margin-top: 2px;
}

.tc-method__h {
  margin: 10px 0 0;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--tc-ink-soft);
}

.tc-method__p {
  margin: 0;
  max-width: 70ch;
  color: var(--tc-ink);
  text-wrap: pretty;
}

/* --- Input region --------------------------------------------------------- */

.tc-input {
  display: grid;
  gap: 16px;
  padding: clamp(16px, 2.4vw, 22px);
  background: var(--tc-ground);
  border: 1px solid var(--tc-divider);
  border-radius: var(--tc-radius-md);
}

.tc-input__legend {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--tc-ink-soft);
}

/* --- Result region -------------------------------------------------------- */

.tc-result {
  display: grid;
  gap: 12px;
}

.tc-result__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--tc-ink-soft);
}

/* --- Source + date footer ------------------------------------------------- */

.tc-foot {
  display: grid;
  gap: 8px;
  padding-top: 16px;
  border-top: 1px solid var(--tc-divider);
}

.tc-foot__label {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--tc-ink-soft);
}

.tc-foot__list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.tc-foot__item {
  margin: 0;
}

/* ==========================================================================
   2. PROVENANCE CHIP
   ========================================================================== */

.tc-chip,
.tc-tool .stamp--chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 11px;
  border: 1px solid var(--tc-edge);
  border-radius: 999px;
  background: var(--tc-quiet);
  color: var(--tc-ink);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: .01em;
  text-transform: none;
  font-variant-numeric: tabular-nums;
  /* Kill the tilt/double-border the site-wide .stamp rules would apply. */
  transform: none;
}

/* A dot, not a checkmark. A checkmark asserts verification. */
.tc-chip::before,
.tc-tool .stamp--chip::before {
  content: "";
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--tc-edge);
  -webkit-mask: none;
  mask: none;
}

.tc-tool .stamp--chip::after {
  display: none;
}

.tc-chip--held {
  background: var(--tc-warm);
}

.tc-chip--held::before {
  background: var(--tc-ink-soft);
}

/* ==========================================================================
   3. FACTS + THE HONEST BLANK
   ========================================================================== */

.tc-field {
  display: grid;
  gap: 6px;
  padding: 14px 16px;
  background: var(--tc-surface);
  border: 1px solid var(--tc-edge);
  border-radius: var(--tc-radius-md);
}

.tc-field__label {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--tc-ink-soft);
}

/* A populated value and an honest blank share ONE declaration. They render at
   the same size, weight and colour because they are the same rule. Splitting
   them is how a blank quietly becomes a greyed-out apology. Do not split them. */
.tc-field__value,
.tc-field__state {
  margin: 0;
  font-size: 19px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--tc-ink);
  font-variant-numeric: tabular-nums;
}

.tc-field__note {
  margin: 0;
  max-width: 62ch;
  font-size: 14px;
  color: var(--tc-ink);
  text-wrap: pretty;
}

.tc-field__where {
  margin: 0;
  font-size: 14px;
  color: var(--tc-ink);
}

.tc-field__where a {
  color: var(--tc-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 2px;
}

/* The honest blank. Differentiated by a sand edge, NOT by being quieter.
   No opacity, no grey, no italics, no smaller type. */
.tc-field--blank {
  background: var(--tc-surface);
  border-color: var(--tc-edge);
  border-left: 6px solid var(--tc-warm);
}

/* ==========================================================================
   4. HELD OUTPUT
   ========================================================================== */

.tc-held {
  position: relative;
  display: grid;
  gap: 10px;
  padding: 18px 18px 18px 22px;
  background: var(--tc-surface);
  border: 1px solid var(--tc-edge);
  border-radius: var(--tc-radius-md);
  overflow: hidden;
}

/* Coral appears here and nowhere else in the chassis. Decoration only. */
.tc-held__rule {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: 6px;
  background: var(--tc-alert);
}

.tc-held__title {
  margin: 0;
  font-size: 18px;
  font-weight: 700;
  color: var(--tc-ink);
}

.tc-held__ran {
  margin: 0;
  padding-inline-start: 20px;
  display: grid;
  gap: 4px;
  color: var(--tc-ink);
}

.tc-held__missing,
.tc-held__who {
  display: grid;
  gap: 4px;
  margin: 0;
  padding: 12px 14px;
  background: var(--tc-quiet);
  border-radius: var(--tc-radius-sm);
}

.tc-held__missing dt,
.tc-held__who dt {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--tc-ink-soft);
}

.tc-held__missing dd,
.tc-held__who dd {
  margin: 0;
  color: var(--tc-ink);
  text-wrap: pretty;
}

/* ==========================================================================
   5. FORM PRIMITIVES
   ========================================================================== */

.tc-form {
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  align-items: start;
}

.tc-control {
  display: grid;
  gap: 6px;
  min-width: 0;
}

.tc-label {
  font-size: 14px;
  font-weight: 700;
  color: var(--tc-ink);
}

.tc-hint {
  margin: 0;
  font-size: 13px;
  color: var(--tc-ink-soft);
  text-wrap: pretty;
}

.tc-select,
.tc-text {
  width: 100%;
  min-height: var(--tc-tap);
  padding: 10px 14px;
  color: var(--tc-ink);
  background: var(--tc-surface);
  border: 1px solid var(--tc-edge);
  border-radius: var(--tc-radius-sm);
  font: inherit;
  font-size: 16px; /* 16px stops iOS zooming the page on focus. */
  transition: border-color var(--tc-t-control) var(--tc-ease);
}

.tc-select {
  cursor: pointer;
  /* Native control, native arrow. No custom dropdown. */
  appearance: auto;
}

textarea.tc-text {
  min-height: 96px;
  resize: vertical;
}

.tc-select:hover,
.tc-text:hover {
  border-color: var(--tc-ink);
}

.tc-select[aria-invalid="true"],
.tc-text[aria-invalid="true"] {
  border-color: var(--tc-ink);
  border-width: 3px;
}

.tc-select:disabled,
.tc-text:disabled {
  background: var(--tc-quiet);
  border-style: dashed;
  cursor: not-allowed;
}

/* Inline validation. Pacific 900 text — coral on foam is 2.53:1 and fails.
   The coral marker bar carries the colour cue; the words carry the meaning. */
.tc-error {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 0;
  padding: 8px 10px;
  font-size: 14px;
  font-weight: 600;
  color: var(--tc-ink);
  background: var(--tc-quiet);
  border-radius: var(--tc-radius-sm);
  text-wrap: pretty;
}

.tc-error::before {
  content: "";
  flex: none;
  width: 4px;
  align-self: stretch;
  min-height: 1.2em;
  border-radius: 2px;
  background: var(--tc-alert);
}

.tc-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
}

.tc-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: var(--tc-tap);
  min-width: var(--tc-tap);
  padding: 11px 20px;
  font: inherit;
  font-weight: 700;
  border-radius: var(--tc-radius-sm);
  border: 1px solid var(--tc-ink);
  background: var(--tc-surface);
  color: var(--tc-ink);
  cursor: pointer;
  transition:
    background-color var(--tc-t-control) var(--tc-ease),
    color var(--tc-t-control) var(--tc-ease);
}

.tc-btn:hover {
  background: var(--tc-quiet);
}

.tc-btn:active {
  background: var(--tc-quiet);
}

.tc-btn--primary {
  /* Pacific 900 / white = 11.68:1. Ocean 600 / white = 4.18:1 and would fail. */
  background: var(--tc-ink);
  color: var(--tc-white);
  border-color: var(--tc-ink);
}

.tc-btn--primary:hover {
  background: var(--pacific-700);
  border-color: var(--pacific-700);
}

.tc-btn--quiet {
  background: var(--tc-surface);
  color: var(--tc-ink);
  border-color: var(--tc-edge);
}

.tc-btn:disabled {
  cursor: not-allowed;
  background: var(--tc-quiet);
  color: var(--tc-ink-soft);
  border-color: var(--tc-edge);
  border-style: dashed;
}

/* ==========================================================================
   6. STATUS, LIVE REGION, NO-JS
   ========================================================================== */

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

.tc-status {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0;
  padding: 10px 14px;
  font-size: 14px;
  font-weight: 600;
  color: var(--tc-ink);
  background: var(--tc-quiet);
  border-radius: var(--tc-radius-sm);
  text-wrap: pretty;
}

.tc-status::before {
  content: "";
  flex: none;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--tc-edge);
}

/* Motion is additive here. The word "Checking…" is always in the DOM, so a
   user who never sees the pulse loses nothing. */
.tc-status--busy::before {
  background: var(--tc-live);
  animation: tc-pulse 1.6s var(--tc-ease) infinite;
}

@keyframes tc-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.5); }
}

.tc-nojs {
  display: none;
  margin: 0;
  padding: 12px 14px;
  font-size: 14px;
  color: var(--tc-ink);
  background: var(--tc-warm);
  border-radius: var(--tc-radius-sm);
  text-wrap: pretty;
}

html:not(.js) .tc-nojs {
  display: block;
}

html:not(.js) [data-tc-js-only] {
  display: none !important;
}

/* ==========================================================================
   7. REDUCED MOTION
   Removes every transition, animation and smooth scroll. Nothing is hidden,
   nothing is collapsed, no state becomes unreadable: the complete story
   survives because motion was never carrying it.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .tc-tool {
    --tc-t-control: 1ms;
    --tc-t-panel: 1ms;
    --tc-t-enter: 1ms;
  }

  .tc-tool *,
  .tc-tool *::before,
  .tc-tool *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }

  .tc-btn:active {
    transform: none;
  }

  .tc-status--busy::before {
    animation: none;
    transform: none;
  }
}

/* ==========================================================================
   8. FORCED COLORS
   High-contrast / forced-colors modes strip our palette. Keep the focus ring
   and every boundary perceivable rather than letting the chassis dissolve.
   ========================================================================== */

@media (forced-colors: active) {
  .tc-tool,
  .tc-field,
  .tc-held,
  .tc-method,
  .tc-input,
  .tc-chip,
  .tc-tool .stamp--chip {
    border: 1px solid CanvasText;
  }

  .tc-tool :focus-visible,
  .tc-tool:focus-visible {
    outline: 3px solid Highlight;
    box-shadow: none;
  }

  .tc-held__rule,
  .tc-error::before {
    background: CanvasText;
    forced-color-adjust: none;
  }
}

/* ==========================================================================
   9. NARROW VIEWPORTS
   ========================================================================== */

@media (max-width: 620px) {
  .tc-form {
    grid-template-columns: 1fr;
  }

  .tc-actions .tc-btn {
    flex: 1 1 100%;
  }

  .tc-result__head {
    flex-direction: column;
    align-items: flex-start;
  }
}
