/*
Theme Name: Datacraft WS
Theme URI: https://datacraft.ws
Author: Tim Chen
Author URI: https://datacraft.ws
Description: Client-facing block theme for the Datacraft analytics consultancy. Direction "Terminal Warm" — warm off-black ground, soft amber accent, monospace-forward headings, sharp corners. Enterprise-scale information architecture at independent-consultant scale. Ships JSON-LD structured data, a dependency-free contact form, a Work case-study post type, and a full library of block patterns. No build step, no bundler, no npm, no external font requests.
Version: 1.1.3
Requires at least: 6.6
Tested up to: 6.8
Requires PHP: 7.4
License: MIT
License URI: https://opensource.org/licenses/MIT
Text Domain: datacraft-ws
Tags: block-patterns, full-site-editing, business, dark, one-column, custom-menu, custom-logo, translation-ready, accessibility-ready

Business details — legal name, email, phone, social profiles, service area —
live in Settings -> Datacraft, never in this theme. See README.md.
*/

/* ==========================================================================
   Datacraft WS — stylesheet
   Direction: "Terminal Warm" (Brand Essence Brief 8.4)
   dark + warm . monospace-forward . sharp corners . tight spacing

   Tokens come from theme.json as --wp--preset--* custom properties. The short
   aliases below exist so the hand-written component CSS stays readable and so
   this file stays diffable against the static site it descends from. Change a
   colour in theme.json, not here.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Token aliases
   -------------------------------------------------------------------------- */

:root {
  --bg:            var(--wp--preset--color--base);
  --surface:       var(--wp--preset--color--surface);
  --surface-2:     var(--wp--preset--color--surface-2);
  --hairline:      var(--wp--preset--color--hairline);
  --hairline-soft: #262019;

  --ink:           var(--wp--preset--color--contrast);
  --ink-secondary: var(--wp--preset--color--ink-secondary);
  --ink-muted:     var(--wp--preset--color--ink-muted);

  --accent:        var(--wp--preset--color--accent);
  --accent-strong: var(--wp--preset--color--accent-strong);
  --accent-wash:   rgba(217, 138, 58, 0.10);

  --font-mono: var(--wp--preset--font-family--mono);
  --font-sans: var(--wp--preset--font-family--sans);

  --step-1: 0.25rem;  --step-2: 0.5rem;   --step-3: 0.75rem;
  --step-4: 1rem;     --step-5: 1.5rem;   --step-6: 2rem;
  --step-7: 3rem;     --step-8: 4.5rem;   --step-9: 6rem;
  --step-10: 8rem;    --step-11: 10rem;

  --container: 76rem;
  --measure:   40rem;

  /* A fourth surface, below the ground rather than above it.

     The palette had three levels going up (bg -> surface -> surface-2) and
     none going down, so the footer and the ground were the same colour and
     the page just stopped. One step darker gives the page a floor. */
  --bg-deep: #0f0c0a;

  /* Easing. One curve for everything that moves, so the motion reads as one
     system rather than as several. */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

/* --------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img, svg, video { max-width: 100%; height: auto; display: block; }

a { text-decoration: none; }

/* Prose links keep the hairline underline the static site used. Navigation,
   buttons and card titles opt out via their own rules — a nav full of
   underlines reads as noise. */
.dc-prose a,
.wp-block-post-content a {
  border-bottom: 1px solid rgba(217, 138, 58, 0.35);
  transition: color 0.15s ease, border-color 0.15s ease;
}

.dc-prose a:hover,
.dc-prose a:focus-visible,
.wp-block-post-content a:hover,
.wp-block-post-content a:focus-visible { border-bottom-color: var(--accent-strong); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

::selection { background: var(--accent); color: var(--bg); }

hr.wp-block-separator {
  border: 0;
  border-top: 1px solid var(--hairline);
  opacity: 1;
  width: 100%;
  max-width: none;
}

/* Every corner is sharp. This direction has no rounded anything. */
.wp-block-button__link,
.wp-block-image img,
.wp-block-group,
input, textarea, select, button { border-radius: 0 !important; }

/* --------------------------------------------------------------------------
   3. Skip link
   -------------------------------------------------------------------------- */

/* Core prints the only skip link (#wp-skip-link, class
   "skip-link screen-reader-text"), targeting the <main id="dc-main"> every
   template renders. These rules restyle it.

   The .screen-reader-text pair is not redundant: core's own
   .screen-reader-text:focus sets a light-grey background and a blue link
   colour at equal specificity to a bare .skip-link:focus, so whichever
   stylesheet loads last would win. Matching both classes raises specificity
   and settles it — otherwise the first thing a keyboard user sees on this
   site is a grey-on-blue box. */
.skip-link,
.skip-link.screen-reader-text {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--accent);
  color: var(--bg);
  padding: var(--step-2) var(--step-4);
  font-family: var(--font-mono);
  font-size: 0.85rem;
  text-decoration: none;
  border: 0;
  clip: auto;
  clip-path: none;
  width: auto;
  height: auto;
}

.skip-link:focus,
.skip-link.screen-reader-text:focus {
  left: var(--step-4);
  top: var(--step-2);
  background: var(--accent);
  color: var(--bg);
  clip: auto;
  clip-path: none;
  width: auto;
  height: auto;
  display: block;
}

/* --------------------------------------------------------------------------
   4. Type utilities — the workhorses of this direction
   -------------------------------------------------------------------------- */

.dc-eyebrow {
  font-family: var(--font-mono) !important;
  font-size: var(--wp--preset--font-size--eyebrow) !important;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 var(--step-3);
}

.dc-eyebrow--muted { color: var(--ink-muted); }

.dc-lede {
  font-size: var(--wp--preset--font-size--large) !important;
  color: var(--ink-secondary);
  line-height: 1.6;
  max-width: 52ch;
}

.dc-mono { font-family: var(--font-mono) !important; }
.dc-muted { color: var(--ink-muted); }
.dc-secondary { color: var(--ink-secondary); }
.dc-measure { max-width: var(--measure); }

.dc-prose { max-width: var(--measure); }
.dc-prose > p, .dc-prose > ul, .dc-prose > ol { color: var(--ink-secondary); }
.dc-prose strong { color: var(--ink); font-weight: 600; }
.dc-prose--wide { max-width: 52rem; }

/* Schema / code sample — monospace, sharp, amber-ruled on the left */
.dc-schema {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  line-height: 1.7;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-left: 2px solid var(--accent);
  padding: var(--step-4);
  overflow-x: auto;
  color: var(--ink-secondary);
  white-space: pre;
}

.dc-schema b { color: var(--ink); font-weight: 600; }

/* Inline TODO marker — visible, greppable, meant to be removed */
.dc-todo {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bg);
  background: var(--accent);
  padding: 0.1em 0.45em;
}

/* --------------------------------------------------------------------------
   5. Section rhythm

   Every top-level band carries a hairline top rule. That single repeated rule
   is most of what makes the page read as ordered rather than as a stack of
   unrelated cards (Brief 3 Precision, 3 Independent discipline).
   -------------------------------------------------------------------------- */

.dc-section {
  padding-block: var(--step-7);
  border-top: 1px solid var(--hairline);
}

.dc-section--flush { border-top: 0; }
.dc-section--tight { padding-block: var(--step-6); }

@media (min-width: 48rem) {
  .dc-section { padding-block: var(--step-8); }
  .dc-section--tight { padding-block: var(--step-7); }
}

/* A band that inverts to the raised surface — used sparingly, for the stat
   band and the closing CTA only. More than two per page and the hairline
   rhythm stops doing its job. */
.dc-section--surface { background: var(--surface); }

/* --------------------------------------------------------------------------
   6. Header / nav
   -------------------------------------------------------------------------- */

.dc-header {
  border-bottom: 1px solid var(--hairline);
  background: var(--bg);
  position: sticky;
  top: 0;
  z-index: 50;
}

/* The WordPress admin bar is fixed on desktop and static on mobile; without
   this the sticky header slides under it. */
.admin-bar .dc-header { top: 32px; }
@media (max-width: 782px) { .admin-bar .dc-header { top: 0; } }

.dc-header .wp-block-group { min-height: 4rem; }

/* Wordmark — renders as "~/datacraft*" with an amber shell-prompt prefix and
   an amber block cursor. Both are CSS pseudo-elements, so the link's
   accessible name stays the plain site title and one rule covers every
   instance. There is deliberately no gap before "~/": it has to read as one
   path, so the cursor's spacing comes from its own margin instead. */
.dc-wordmark a,
.dc-wordmark .wp-block-site-title a {
  color: var(--ink) !important;
  border-bottom: 0;
  display: inline-flex;
  align-items: baseline;
  font-family: var(--font-mono);
  font-weight: 600;
  letter-spacing: -0.02em;
  text-transform: lowercase;
}

.dc-wordmark a::before { content: "~/"; color: var(--accent); }

.dc-wordmark a::after {
  content: "";
  display: inline-block;
  width: 0.5em;
  height: 0.95em;
  margin-left: 0.15em;
  background: var(--accent);
  transform: translateY(0.08em);
}

/* Navigation */
.dc-nav .wp-block-navigation-item__content {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  letter-spacing: 0.06em;
  color: var(--ink-secondary);
  border-bottom: 1px solid transparent;
  padding-block: var(--step-1);
}

.dc-nav .wp-block-navigation-item__content:hover,
.dc-nav .wp-block-navigation-item__content:focus-visible,
.dc-nav .current-menu-item > .wp-block-navigation-item__content {
  color: var(--ink);
  border-bottom-color: var(--accent);
}

/* Submenu — the one place this theme borrows the reference site's mega-nav
   idea, scaled down to a single flat column of services. */
.dc-nav .wp-block-navigation__submenu-container {
  background: var(--surface) !important;
  border: 1px solid var(--hairline) !important;
  padding: var(--step-2) 0;
  min-width: 16rem;
}

.dc-nav .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
  padding: var(--step-2) var(--step-4);
  border-bottom: 0;
  width: 100%;
}

.dc-nav .wp-block-navigation__submenu-container .wp-block-navigation-item__content:hover {
  color: var(--accent);
  background: var(--surface-2);
}

/* Mobile overlay */
.dc-nav .wp-block-navigation__responsive-container.is-menu-open {
  background: var(--bg) !important;
  padding: var(--step-6) var(--step-5);
}

.dc-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
  font-size: 1.05rem;
}

/* The header CTA is a button, not a nav link — it must not inherit the
   underline-on-hover treatment. */
.dc-header-cta .wp-block-button__link { border-bottom: 0; }

/* --------------------------------------------------------------------------
   7. Hero
   -------------------------------------------------------------------------- */

.dc-hero {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  padding-block: var(--step-7);
  border-top: 0;
}

@media (min-width: 48rem) { .dc-hero { padding-block: var(--step-8) var(--step-8); } }

.dc-hero h1 { max-width: 22ch; }
.dc-hero .dc-lede { max-width: 52ch; }

.dc-hero__media {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}

.dc-hero__canvas {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
}

.dc-hero__media [hidden] { display: none; }

/* Scrim — holds heavy across the whole headline measure, then falls off a
   cliff just past where the type ends (~70%) so the right of the frame stays
   brilliant. The knee is the whole trick: fading evenly across the full width
   either washes out the field or fails contrast. Do not slide the 70% stop
   rightward without re-measuring; the headline reaches 69% of the viewport
   once the container widens at 100rem. */
.dc-hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to right,
      rgba(20, 17, 14, 0.94) 0%,
      rgba(20, 17, 14, 0.90) 35%,
      rgba(20, 17, 14, 0.66) 70%,
      rgba(20, 17, 14, 0.22) 80%,
      rgba(20, 17, 14, 0) 100%),
    linear-gradient(to bottom,
      var(--bg) 0%,
      rgba(20, 17, 14, 0.15) 20%,
      rgba(20, 17, 14, 0.15) 74%,
      var(--bg) 100%);
}

/* Inner page hero — no media, just the hairline and the measure */
.dc-page-hero { padding-block: var(--step-7) var(--step-6); border-top: 0; }
.dc-page-hero h1 { max-width: 26ch; }

@media (min-width: 48rem) {
  .dc-page-hero { padding-block: var(--step-8) var(--step-7); }
}

/* --------------------------------------------------------------------------
   8. Buttons
   -------------------------------------------------------------------------- */

.wp-block-button__link {
  display: inline-flex;
  align-items: center;
  gap: var(--step-2);
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.wp-block-button.is-style-outline > .wp-block-button__link,
.dc-btn-ghost .wp-block-button__link {
  background: transparent !important;
  color: var(--ink) !important;
  border: 1px solid var(--hairline) !important;
}

.wp-block-button.is-style-outline > .wp-block-button__link:hover,
.dc-btn-ghost .wp-block-button__link:hover {
  color: var(--accent) !important;
  border-color: var(--accent) !important;
  background: transparent !important;
}

/* Text-only "read on" affordance */
.dc-more {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  color: var(--accent);
  display: inline-block;
}

.dc-more::after { content: " \2192"; }

/* --------------------------------------------------------------------------
   9. Trust bar — named tools stand in for the client-logo row the reference
   site runs. Naming the stack explicitly is a Brief 5 non-negotiable, and it
   is honest: these are tools, not client endorsements.
   -------------------------------------------------------------------------- */

.dc-trustbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--step-3) var(--step-5);
  list-style: none;
  margin: 0;
  padding: 0;
}

.dc-trustbar li {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0;
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   10. Grids
   -------------------------------------------------------------------------- */

.dc-grid { display: grid; gap: var(--step-5); }

@media (min-width: 40rem) { .dc-grid--2 { grid-template-columns: repeat(2, 1fr); } }

@media (min-width: 52rem) {
  .dc-grid--3 { grid-template-columns: repeat(3, 1fr); }
  .dc-grid--4 { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 68rem) { .dc-grid--4 { grid-template-columns: repeat(4, 1fr); } }

/* Section head — title left, "see all" right, on one baseline */
.dc-section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--step-3) var(--step-5);
  margin-bottom: var(--step-6);
}

.dc-section-head p { margin: 0; }

/* --------------------------------------------------------------------------
   11. Cards
   -------------------------------------------------------------------------- */

.dc-card {
  background: var(--surface);
  border: 1px solid var(--hairline);
  padding: var(--step-5);
  margin: 0;
  display: flex;
  flex-direction: column;
  transition: border-color 0.15s ease;
}

.dc-card:hover,
.dc-card:focus-within { border-color: var(--accent); }

.dc-card h3 { margin: 0 0 var(--step-3); }

.dc-card h3 a { color: var(--ink); border-bottom: 1px solid transparent; }

.dc-card h3 a:hover,
.dc-card h3 a:focus-visible { color: var(--accent); border-bottom-color: var(--accent); }

.dc-card p { color: var(--ink-secondary); font-size: 0.95rem; margin: 0 0 var(--step-4); }

.dc-card > :last-child { margin-top: auto; margin-bottom: 0; }

.dc-card__meta {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 var(--step-3);
  display: flex;
  flex-wrap: wrap;
  gap: var(--step-3);
}

.dc-card__figure { margin: 0 0 var(--step-4); border: 1px solid var(--hairline); }

/* Numbered card — the process row. The index is set in the markup rather
   than by a CSS counter so it survives being reordered in the editor. */
.dc-card__index {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  color: var(--accent);
  margin: 0 0 var(--step-3);
}

/* Placeholder-state card — used where real work is still being written up */
.dc-card--pending {
  background: transparent;
  border-style: dashed;
  color: var(--ink-muted);
}

.dc-card--pending:hover { border-color: var(--hairline); }

/* --------------------------------------------------------------------------
   12. Stat band — the at-a-glance layer (Brief 6 Density)

   Hairline-gapped grid: a 1px gap over a hairline-coloured background paints
   the internal rules, so there is no double border where cells meet.
   -------------------------------------------------------------------------- */

.dc-stats {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1px;
  background: var(--hairline);
  border: 1px solid var(--hairline);
}

@media (min-width: 44rem) {
  .dc-stats--2 { grid-template-columns: repeat(2, 1fr); }
  .dc-stats--3 { grid-template-columns: repeat(3, 1fr); }
  .dc-stats--4 { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 64rem) { .dc-stats--4 { grid-template-columns: repeat(4, 1fr); } }

.dc-stat { background: var(--surface); padding: var(--step-5); margin: 0; }

.dc-stat__val {
  font-family: var(--font-mono);
  font-size: var(--wp--preset--font-size--stat);
  font-weight: 600;
  color: var(--accent);
  line-height: 1.1;
  display: block;
  margin-bottom: var(--step-2);
}

.dc-stat__label { font-size: 0.875rem; color: var(--ink-secondary); margin: 0; }

.dc-stat__note {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  color: var(--ink-muted);
  margin: var(--step-2) 0 0;
}

/* --------------------------------------------------------------------------
   13. Spec list — key/value in mono. Used for engagement scope, deliverables
   and timelines, where the reference site would run a feature table.
   -------------------------------------------------------------------------- */

.dc-spec { margin: 0; border-top: 1px solid var(--hairline); }

.dc-spec__row {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--step-1);
  padding-block: var(--step-3);
  border-bottom: 1px solid var(--hairline-soft);
}

@media (min-width: 40rem) {
  .dc-spec__row { grid-template-columns: 12rem 1fr; gap: var(--step-5); align-items: baseline; }
}

.dc-spec__key {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0;
}

.dc-spec__val { margin: 0; color: var(--ink); font-size: 0.95rem; }

/* Checklist — deliverables. The marker is an amber monospace arrow rather
   than a bullet, which keeps the technical register. */
.dc-check { list-style: none; margin: 0; padding: 0; }

.dc-check li {
  position: relative;
  padding-left: 1.5rem;
  margin-bottom: var(--step-3);
  color: var(--ink-secondary);
  font-size: 0.95rem;
}

.dc-check li::before {
  content: "\2192";
  position: absolute;
  left: 0;
  top: 0;
  font-family: var(--font-mono);
  color: var(--accent);
}

/* --------------------------------------------------------------------------
   14. Figures — real screenshots are first-class content (Brief 3 Evidence)
   -------------------------------------------------------------------------- */

.dc-figure { margin: var(--step-6) 0; }

.dc-figure img { width: 100%; border: 1px solid var(--hairline); background: var(--surface); }

.dc-figure figcaption,
.wp-block-image figcaption {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  line-height: 1.6;
  color: var(--ink-muted);
  margin-top: var(--step-3);
  padding-left: var(--step-3);
  border-left: 2px solid var(--accent);
  text-align: left;
}

.dc-figure--portrait img { max-width: 22rem; }

/* Pull quote / emphasis line */
.dc-pull {
  border-left: 2px solid var(--accent);
  padding: var(--step-2) 0 var(--step-2) var(--step-4);
  margin: var(--step-6) 0;
  color: var(--ink);
  font-size: 1.05rem;
}

/* --------------------------------------------------------------------------
   15. FAQ — native details/summary. No JavaScript, keyboard-operable for
   free, and the content is in the DOM for the FAQPage JSON-LD to match.
   -------------------------------------------------------------------------- */

.dc-faq { border-top: 1px solid var(--hairline); }

.dc-faq__item { border-bottom: 1px solid var(--hairline); }

.dc-faq__item summary {
  cursor: pointer;
  list-style: none;
  padding: var(--step-4) 2.5rem var(--step-4) 0;
  position: relative;
  font-family: var(--font-mono);
  font-size: 0.95rem;
  color: var(--ink);
}

.dc-faq__item summary::-webkit-details-marker { display: none; }

.dc-faq__item summary::after {
  content: "+";
  position: absolute;
  right: var(--step-2);
  top: var(--step-4);
  font-family: var(--font-mono);
  color: var(--accent);
  font-size: 1.1rem;
  line-height: 1.4;
}

.dc-faq__item[open] summary::after { content: "\2212"; }

.dc-faq__item summary:hover { color: var(--accent); }

.dc-faq__answer { padding: 0 0 var(--step-5); color: var(--ink-secondary); max-width: var(--measure); }

.dc-faq__answer p:last-child { margin-bottom: 0; }

/* --------------------------------------------------------------------------
   16. Forms
   -------------------------------------------------------------------------- */

.dc-form { max-width: 34rem; }

.dc-form .dc-field { margin-bottom: var(--step-5); }

.dc-form label {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-secondary);
  margin-bottom: var(--step-2);
}

.dc-form .dc-hint {
  display: block;
  font-family: var(--font-sans);
  font-size: 0.8rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-muted);
  margin-top: var(--step-1);
}

.dc-form input,
.dc-form textarea,
.dc-form select {
  width: 100%;
  font-family: var(--font-sans);
  font-size: 1rem;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--hairline);
  padding: var(--step-3);
  transition: border-color 0.15s ease;
}

.dc-form input:hover,
.dc-form textarea:hover,
.dc-form select:hover { border-color: var(--ink-muted); }

.dc-form input:focus,
.dc-form textarea:focus,
.dc-form select:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-color: var(--accent);
}

.dc-form textarea { min-height: 9rem; resize: vertical; }

.dc-form input::placeholder,
.dc-form textarea::placeholder { color: var(--ink-muted); }

.dc-form button[type="submit"] {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  padding: var(--step-3) var(--step-5);
  border: 1px solid var(--accent);
  background: var(--accent);
  color: var(--bg);
  cursor: pointer;
  width: auto;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.dc-form button[type="submit"]:hover { background: var(--accent-strong); border-color: var(--accent-strong); }

/* The honeypot is hidden from sight but must stay reachable in the DOM and
   out of the accessibility tree. Not display:none — some bots skip those. */
.dc-hp {
  position: absolute !important;
  left: -9999px !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.dc-notice {
  border: 1px solid var(--hairline);
  border-left: 2px solid var(--accent);
  background: var(--surface);
  padding: var(--step-4);
  margin-bottom: var(--step-5);
  font-size: 0.95rem;
  color: var(--ink);
}

.dc-notice--error { border-left-color: #d9603a; }

.dc-field-error {
  display: block;
  font-family: var(--font-sans);
  font-size: 0.8rem;
  letter-spacing: 0;
  text-transform: none;
  color: #e08a6a;
  margin-top: var(--step-1);
}

.dc-form input[aria-invalid="true"],
.dc-form textarea[aria-invalid="true"] { border-color: #d9603a; }

/* --------------------------------------------------------------------------
   17. Footer
   -------------------------------------------------------------------------- */

.dc-footer {
  border-top: 1px solid var(--hairline);
  padding-block: var(--step-7) var(--step-6);
  margin-top: var(--step-8);
}

.dc-footer__grid { display: grid; gap: var(--step-6); }

@media (min-width: 44rem) {
  .dc-footer__grid { grid-template-columns: 1.6fr 1fr 1fr 1fr; gap: var(--step-6); }
}

.dc-footer h2, .dc-footer h3 {
  font-family: var(--font-mono);
  font-size: 0.72rem !important;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 var(--step-3);
}

.dc-footer ul,
.dc-linklist ul { list-style: none; margin: 0; padding: 0; }
.dc-footer li,
.dc-linklist li { margin-bottom: var(--step-2); }

.dc-footer a,
.dc-linklist a {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  color: var(--ink-secondary);
  border-bottom: 1px solid transparent;
}

.dc-footer a:hover, .dc-footer a:focus-visible,
.dc-linklist a:hover, .dc-linklist a:focus-visible { color: var(--accent); border-bottom-color: var(--accent); }

.dc-footer__blurb { color: var(--ink-secondary); font-size: 0.9rem; max-width: 34ch; margin: var(--step-3) 0 0; }

.dc-footer__legal {
  margin-top: var(--step-7);
  padding-top: var(--step-4);
  border-top: 1px solid var(--hairline-soft);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: var(--ink-muted);
  display: flex;
  flex-wrap: wrap;
  gap: var(--step-2) var(--step-5);
  justify-content: space-between;
}

.dc-footer__legal p { margin: 0; }

/* --------------------------------------------------------------------------
   18. Breadcrumbs
   -------------------------------------------------------------------------- */

.dc-crumbs {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: var(--step-5);
}

.dc-crumbs a { color: var(--ink-muted); }
.dc-crumbs a:hover { color: var(--accent); }
.dc-crumbs span[aria-hidden] { padding: 0 var(--step-2); color: var(--hairline); }

/* --------------------------------------------------------------------------
   19. Query loops — Insights and Work archives inherit the card treatment
   -------------------------------------------------------------------------- */

.wp-block-post-template { list-style: none; padding: 0; }

.dc-loop .wp-block-post-title { font-size: 1.2rem; margin: 0 0 var(--step-3); }
.dc-loop .wp-block-post-title a { color: var(--ink); border-bottom: 1px solid transparent; }
.dc-loop .wp-block-post-title a:hover { color: var(--accent); border-bottom-color: var(--accent); }

.dc-loop .wp-block-post-excerpt__excerpt { color: var(--ink-secondary); font-size: 0.95rem; }

.dc-loop .wp-block-post-date,
.dc-loop .wp-block-post-terms {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.wp-block-query-pagination {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  margin-top: var(--step-7);
  padding-top: var(--step-5);
  border-top: 1px solid var(--hairline);
}

/* --------------------------------------------------------------------------
   20. Large viewports

   At 68rem the column strands ~730px of dead margin each side on a 2560px
   display, and because the hero measures are capped in ch the type fills only
   the left half of that column — which reads as "not centred" even though the
   container is centred exactly. Widen the column and the display measures
   together, or the headline stays pinned to a left edge that just moved
   further out. Body prose does NOT grow: 40rem is already ~80 characters.
   -------------------------------------------------------------------------- */

@media (min-width: 100rem) {
  :root { --container: 80rem; }

  body { --wp--style--global--wide-size: 80rem; }

  .dc-hero h1 { max-width: 38ch; }
  .dc-hero .dc-lede { max-width: 66ch; }
  .dc-page-hero h1 { max-width: 40ch; }
}

/* --------------------------------------------------------------------------
   21. Motion — minimal and functional (Brief 6 Motion). Never gates the
   proof: everything is visible without JavaScript, which only adds the fade.
   -------------------------------------------------------------------------- */

.js .dc-reveal { opacity: 0; transform: translateY(8px); }

.js .dc-reveal.is-visible {
  opacity: 1;
  transform: none;
  transition: opacity 0.45s ease-out, transform 0.45s ease-out;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  .js .dc-reveal,
  .js .dc-reveal.is-visible { opacity: 1; transform: none; transition: none; }

  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* --------------------------------------------------------------------------
   22. Print — a recruiter or a procurement lead printing a service page
   should get the words, not the furniture.
   -------------------------------------------------------------------------- */

@media print {
  .dc-header, .dc-footer, .dc-hero__media, .dc-form { display: none !important; }
  body { background: #fff !important; color: #000 !important; }
  * { color: #000 !important; background: transparent !important; }
}

/* ==========================================================================
   23. Scale and dynamics

   Everything below this line raises the design from "correct" to "built".
   It borrows the *behaviour* of the Auros reference system — cinematic
   spacing, display type at real scale, depth by surface rather than shadow,
   luminous statistics, kinetic display text — and rejects its surface:
   no teal, no lavender, no 16px radii, no geometric sans. The palette and
   the sharp corners are the Datacraft brand and they do not move.

   Ordered last on purpose: these rules intentionally override the component
   defaults above at equal specificity.
   ========================================================================== */

/* --------------------------------------------------------------------------
   23.1 Spatial rhythm — the single biggest difference between a template and
   a designed page. The reference system is explicitly "spacious"; the old
   3rem/4.5rem bands read as a stack of boxes because nothing could breathe.
   -------------------------------------------------------------------------- */

.dc-section {
  padding-block: var(--step-8);
}

@media (min-width: 48rem) {
  .dc-section { padding-block: var(--step-10); }
  .dc-section--tight { padding-block: var(--step-7); }
}

@media (min-width: 90rem) {
  .dc-section { padding-block: var(--step-11); }
}

/* The ground has a floor now. */
body { background: var(--bg); }

.dc-footer {
  background: var(--bg-deep);
  margin-top: 0;
  padding-block: var(--step-10) var(--step-7);
  border-top: 1px solid var(--hairline);
}

.dc-section--surface { background: var(--surface); }

/* --------------------------------------------------------------------------
   23.2 Display type

   Headings are monospace, which costs roughly 15% more width per character
   than a grotesk at the same size — so the measures are in ch and stay tight
   rather than being pinned to a pixel width that would wrap unpredictably.
   -------------------------------------------------------------------------- */

.dc-hero h1 {
  max-width: 17ch;
  text-wrap: balance;
}

.dc-section h2,
.dc-page-hero h1 {
  max-width: 20ch;
  text-wrap: balance;
}

.dc-lede {
  font-size: var(--wp--preset--font-size--large) !important;
  line-height: 1.55;
  max-width: 54ch;
}

/* Section heads get air under them at the new scale. */
.dc-section-head { margin-bottom: var(--step-7); }

.dc-eyebrow { margin-bottom: var(--step-4); }

/* --------------------------------------------------------------------------
   23.3 Hero

   Full-height, so the first screen is composition rather than the top of a
   document. min-height rather than height: the copy must be allowed to push
   it taller on a short laptop viewport instead of being clipped.
   -------------------------------------------------------------------------- */

@media (min-width: 48rem) {
  .dc-hero {
    min-height: min(92vh, 54rem);
    display: flex;
    align-items: center;
    padding-block: var(--step-10);
  }

  .dc-hero > .wp-block-group { width: 100%; }
}

/* A hairline that draws itself in under the hero, tying it to the section
   rhythm below without a hard rule across the fold. */
.dc-hero::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: linear-gradient(to right,
    transparent 0%,
    var(--hairline) 12%,
    var(--hairline) 88%,
    transparent 100%);
}

.dc-hero__actions { margin-top: var(--step-7) !important; }

/* --------------------------------------------------------------------------
   23.4 Buttons — the signature CTA

   The reference system's one chromatic gesture is a gradient pill. Ours is
   an amber sweep: a highlight that travels across the fill on hover. It is a
   pseudo-element rather than a background-position animation because
   gradients on background-position cannot be composited on the GPU, and this
   sits under the primary action on every page.
   -------------------------------------------------------------------------- */

.wp-block-button:not(.is-style-outline) > .wp-block-button__link {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  padding: 0.9rem 1.75rem;
  font-size: 0.84rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.wp-block-button:not(.is-style-outline) > .wp-block-button__link::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(100deg,
    var(--accent) 0%,
    var(--accent-strong) 45%,
    #f3c489 55%,
    var(--accent) 100%);
  background-size: 260% 100%;
  background-position: 100% 0;
  transition: background-position 0.55s var(--ease);
}

.wp-block-button:not(.is-style-outline) > .wp-block-button__link:hover::before,
.wp-block-button:not(.is-style-outline) > .wp-block-button__link:focus-visible::before {
  background-position: 0 0;
}

.wp-block-button.is-style-outline > .wp-block-button__link,
.dc-btn-ghost .wp-block-button__link {
  padding: 0.9rem 1.75rem;
  font-size: 0.84rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   23.5 Cards

   Depth by surface, never by shadow. On hover the card lifts one surface
   step and an amber rule wipes across its top edge — a scale transform would
   resample the monospace type and make it shimmer.
   -------------------------------------------------------------------------- */

.dc-card {
  position: relative;
  padding: var(--step-6);
  overflow: hidden;
  transition: background-color 0.3s var(--ease), border-color 0.3s var(--ease);
}

@media (min-width: 48rem) {
  .dc-card { padding: var(--step-6) var(--step-6) var(--step-6); }
}

.dc-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.45s var(--ease);
}

.dc-card:hover,
.dc-card:focus-within {
  background: var(--surface-2);
  border-color: var(--hairline);
}

.dc-card:hover::before,
.dc-card:focus-within::before { transform: scaleX(1); }

.dc-card h3 { margin-bottom: var(--step-4); }

.dc-card__index {
  font-size: 2.25rem;
  line-height: 1;
  color: var(--hairline);
  letter-spacing: -0.03em;
  margin-bottom: var(--step-5);
  transition: color 0.35s var(--ease);
}

.dc-card:hover .dc-card__index { color: var(--accent); }

/* Arrow affordance — the reference system's "go to" trigger, squared off.
   It travels on hover; the card is the hover target, not the arrow, so the
   whole card reads as one control. */
.dc-more {
  display: inline-flex;
  align-items: center;
  gap: var(--step-2);
  border-bottom: 0;
}

.dc-more::after {
  content: "\2197";
  display: inline-block;
  transition: transform 0.35s var(--ease);
}

.dc-card:hover .dc-more::after,
.dc-more:hover::after,
.dc-more:focus-visible::after { transform: translate(3px, -3px); }

/* --------------------------------------------------------------------------
   23.6 Statistics — luminous punctuation

   The reference system puts its one bright accent on the numbers. Ours are
   amber on the raised surface, at display scale, with tabular figures so a
   counting animation cannot make the row jitter as digits change width.
   -------------------------------------------------------------------------- */

.dc-stats {
  gap: 1px;
  border: 1px solid var(--hairline);
  background: var(--hairline);
}

.dc-stat {
  padding: var(--step-6);
  background: var(--surface);
  transition: background-color 0.35s var(--ease);
}

.dc-stat:hover { background: var(--surface-2); }

.dc-stat__val {
  font-size: var(--wp--preset--font-size--stat);
  line-height: 0.95;
  letter-spacing: -0.04em;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  margin-bottom: var(--step-4);
}

.dc-stat__label { font-size: 0.95rem; line-height: 1.5; max-width: 34ch; }

/* --------------------------------------------------------------------------
   23.7 Kinetic band — oversized display text as an environmental element

   Two copies of the track scroll continuously; the second is aria-hidden and
   exists only so the wrap is seamless. Duplicating the content is what makes
   a marquee loop without a jump — a single track has to snap back.

   translate3d, not left/margin: this animates for the whole time the band is
   on screen, and only a transform stays off the main thread.
   -------------------------------------------------------------------------- */

.dc-kinetic {
  overflow: hidden;
  border-block: 1px solid var(--hairline);
  padding-block: var(--step-6);
  background: var(--bg);
  user-select: none;
}

.dc-kinetic__track {
  display: flex;
  width: max-content;
  gap: var(--step-7);
  will-change: transform;
  animation: dc-marquee 46s linear infinite;
}

.dc-kinetic__item {
  font-family: var(--font-mono);
  font-size: var(--wp--preset--font-size--kinetic);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.045em;
  color: transparent;
  -webkit-text-stroke: 1px var(--hairline);
  white-space: nowrap;
  transition: color 0.4s var(--ease), -webkit-text-stroke-color 0.4s var(--ease);
}

/* Every third item is filled amber, so the band has rhythm rather than
   being a uniform ribbon of outline type. */
.dc-kinetic__item--on {
  color: var(--accent);
  -webkit-text-stroke-color: transparent;
}

.dc-kinetic:hover .dc-kinetic__track { animation-play-state: paused; }

@keyframes dc-marquee {
  from { transform: translate3d(0, 0, 0); }
  /* -50% exactly, because the track holds the content twice. */
  to   { transform: translate3d(-50%, 0, 0); }
}

/* --------------------------------------------------------------------------
   23.8 Scroll progress rail

   A 2px amber rule under the sticky header, scaled by scroll depth. On a
   site whose argument is measurement, a readout of where you are is on
   theme rather than decorative.
   -------------------------------------------------------------------------- */

.dc-progress {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  will-change: transform;
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   23.9 Trust bar — a moving ticker rather than a static list
   -------------------------------------------------------------------------- */

.dc-trustbar li {
  font-size: 0.8rem;
  color: var(--ink-muted);
  transition: color 0.3s var(--ease);
}

.dc-trustbar li:hover { color: var(--accent); }

.dc-trustbar li + li::before {
  content: "\00B7";
  color: var(--hairline);
  margin-right: var(--step-5);
}

/* --------------------------------------------------------------------------
   23.10 Reveals — staggered

   --dc-i is set per element by motion.js; the delay is derived from it so
   siblings arrive in sequence instead of all at once. Capped at 6 steps so a
   twelve-card grid does not take a second and a half to finish.
   -------------------------------------------------------------------------- */

.js .dc-reveal {
  opacity: 0;
  transform: translateY(14px);
}

.js .dc-reveal.is-visible {
  opacity: 1;
  transform: none;
  transition:
    opacity 0.6s var(--ease) calc(var(--dc-i, 0) * 70ms),
    transform 0.6s var(--ease) calc(var(--dc-i, 0) * 70ms);
}

/* --------------------------------------------------------------------------
   23.11 Grids at the wider column
   -------------------------------------------------------------------------- */

.dc-grid { gap: 1px; }

/* Hairline-gapped grids: a 1px gap over a hairline ground paints the
   internal rules, so cards meet without doubling their borders. */
.dc-grid--3,
.dc-grid--4 {
  background: var(--hairline);
  border: 1px solid var(--hairline);
}

.dc-grid--3 > .dc-card,
.dc-grid--4 > .dc-card { border: 0; }

@media (min-width: 52rem) {
  .dc-grid--4 { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 76rem) {
  .dc-grid--4 { grid-template-columns: repeat(4, 1fr); }
}

/* --------------------------------------------------------------------------
   23.12 Header
   -------------------------------------------------------------------------- */

.dc-header {
  position: sticky;
  backdrop-filter: saturate(140%) blur(10px);
  background: rgba(20, 17, 14, 0.86);
}

/* No backdrop-filter support: fall back to the solid ground rather than a
   translucent header with the page legible through it. */
@supports not (backdrop-filter: blur(1px)) {
  .dc-header { background: var(--bg); }
}

/* --------------------------------------------------------------------------
   23.13 Reduced motion

   Everything above is decoration. Under prefers-reduced-motion the marquee
   stops dead (not merely slowed), the reveals are already handled in §21,
   and the progress rail is left in place because it is information, not
   movement.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .dc-kinetic__track { animation: none; transform: none; }
  .dc-kinetic { overflow-x: auto; }
  .dc-more::after,
  .dc-card__index,
  .dc-card::before { transition: none; }
}

/* --------------------------------------------------------------------------
   23.14 Escaping the constrained-layout clamp

   WordPress's constrained layout sets `max-width: contentSize` on every child
   that carries no alignment class. That is correct for prose and wrong for
   anything this theme draws itself: the hero canvas, the grids, the stat
   band and the marquee track are all raw elements inside a block wrapper, so
   all of them were silently squeezed to 40rem inside a 76rem band — which is
   what made the hero field render as a hard-edged column rather than a field.

   The section groups are flow containers now, which fixes it structurally.
   These rules are the belt to that braces: they keep a component full-width
   even if someone later wraps it back in a constrained group in the editor.
   Two classes deep so they beat `.is-layout-constrained > :where(...)`.
   -------------------------------------------------------------------------- */

.dc-hero .dc-hero__media,
.dc-section .dc-grid,
.dc-section .dc-stats,
.dc-section .dc-spec,
.dc-section .dc-faq,
.dc-section .dc-check,
.dc-section .dc-trustbar,
.dc-section .dc-section-head,
.dc-kinetic .dc-kinetic__track {
  max-width: none;
  margin-left: 0;
  margin-right: 0;
}

/* Prose keeps its measure — that clamp is the one we want. */
.dc-section .dc-lede { margin-left: 0; margin-right: 0; }

/* --------------------------------------------------------------------------
   23.15 Specificity fixes inside cards

   `.dc-card p` sets the body size for card copy at specificity (0,1,1). Both
   the step numeral and the category label are <p> elements, so their own
   single-class rules — (0,1,0) — lost to it and rendered at body size no
   matter where they sat in the file. Qualifying them by element brings them
   level and past it.

   Worth remembering when adding anything to a card: a bare component class
   will not beat `.dc-card p`.
   -------------------------------------------------------------------------- */

p.dc-card__index {
  font-size: 2.25rem;
  line-height: 1;
  color: var(--hairline);
  letter-spacing: -0.03em;
  margin-bottom: var(--step-5);
  font-variant-numeric: tabular-nums;
}

.dc-card:hover p.dc-card__index,
.dc-card:focus-within p.dc-card__index { color: var(--accent); }

p.dc-card__meta {
  font-size: var(--wp--preset--font-size--eyebrow);
  letter-spacing: 0.14em;
  color: var(--ink-muted);
  margin-bottom: var(--step-4);
}
