/* ==========================================================================
   ATEX DIGITAL · tokens.css
   --------------------------------------------------------------------------
   01 · RESET
   02 · DESIGN TOKENS
   03 · BASE TYPOGRAPHY
   04 · LAYOUT · container / section / grid / spans
   05 · SHARED UTILITIES · seam / eyebrow / reveal / beat
   06 · ACCESSIBILITY UTILITIES
   07 · REDUCED MOTION
   ========================================================================== */


/* ===== 01 · RESET ===================================================== */

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

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

body,
h1, h2, h3, h4, h5, h6,
p, figure, blockquote, dl, dd, ul, ol {
  margin: 0;
}

ul[class], ol[class] {
  padding: 0;
  list-style: none;
}

img, svg, video, canvas {
  display: block;
  max-inline-size: 100%;
}

img { block-size: auto; }

button, input, select, textarea {
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
}

button {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

a {
  color: inherit;
  text-decoration: none;
}

:focus-visible {
  outline: 2px solid var(--azure);
  outline-offset: 3px;
  border-radius: 2px;
}

/* Text on an accent fill always takes --ink-950, never the page ground.
   On lime either would do (12.1:1 vs 14.6:1), but on magenta the ground is
   only 3.85:1 while --ink-950 clears AA at 4.62:1. One rule, always right. */
::selection {
  background: var(--azure);
  color: var(--ink-950);
}


/* ===== 02 · DESIGN TOKENS ============================================= */

:root {

  /* ---- surface ladder · deep petrol teal, built up from the supplied
         ground. --ink-900 IS that ground; every other rung is the same hue
         stepped around it so cards still read as raised and the alt band
         still reads as recessed.
         The ladder is tighter than the old near-black one had to be, and
         that is forced, not stylistic: a lighter ground eats contrast
         headroom, and --ink-700 is capped at L=0.041 because above that
         --bone-dim body copy drops under 4.5:1. ---- */
  --ink-950: #061C27;   /* also the text colour on any accent fill — see below */
  --ink-900: #0E2C3D;   /* THE GROUND */
  --ink-850: #103044;
  --ink-800: #13374B;
  --ink-700: #173D53;
  --ink-600: #20506A;

  /* ---- seams ---- */
  --line:        #1E4A62;
  --line-hi:     #2E6884;
  --line-brand:  rgba(191, 255, 0, .34);
  --line-signal: rgba(255, 0, 128, .34);

  /* ---- type · cool bone, like screen-printed console labels.
         --bone-dim and --bone-faint were both lifted a step when the ground
         moved to teal: at their old values --bone-dim measured 4.0:1 on
         --ink-700, under the AA floor it had cleared comfortably against
         near-black. --bone and --bone-2 needed no change. ---- */
  --bone:       #ECF1F7;
  --bone-2:     #BCC6D4;
  --bone-dim:   #98A6B6;   /* was #8E9AAC */
  --bone-faint: #6A7B8B;   /* was #5B6678 · decorative only — never body copy */

  /* ---- BRAND · lime. Owns structure and state: navigation, focus, active
         tabs, hover, selection. Never means "earning".
         This is the accent that carries almost every link, label and nav
         state, so it has to be the high-contrast one of the pair: 16.4:1 on
         the ground, against magenta's 5.2:1. Swapping the two roles would
         put 4.26:1 text on --ink-700 panels, under the 4.5:1 AA floor. ---- */
  --azure:      #BFFF00;
  --azure-hi:   #D2FF4F;
  --azure-soft: #E4FFA0;
  --azure-glow: rgba(191, 255, 0, .18);
  --azure-wash: rgba(191, 255, 0, .07);

  /* ---- SIGNAL · magenta. The VU meter. Before colouring anything with
         this, answer: is this thing live, active, or earning?
         Deliberately the rarer of the two, and the shallower of the two.
         As a FILL it now carries white type by explicit choice — see the note
         on .btn--solid. That is 3.77:1 and under the AA floor; --ink-950 was
         4.62:1. Deepening the fill to #E00071 would buy white 4.76:1 if the
         rule ever needs to hold.
         As TEXT magenta is only ever used at display sizes, where the AA floor
         is 3:1. At body size on --ink-700 it measures 3.04:1 and on the ground
         3.85:1 — use --signal-soft for small magenta text. ---- */
  --signal:      #FF0080;
  --signal-hi:   #FF3D9E;
  --signal-soft: #FF9ECE;
  --signal-glow: rgba(255, 0, 128, .18);
  --signal-wash: rgba(255, 0, 128, .07);

  /* ---- DEPTH · the dark end of the signal magenta, not a third hue. It
         fills the logo dot and the two big radial washes, both of which sit
         near 2:1 against the ground and are meant to. The solid value was
         lifted with the ground — at #7A1060 the mark's dot fell to 1.4:1 on
         teal and effectively disappeared; #B01A7A restores it to 2.3:1,
         which is where it sat on the old near-black. The wash stays deep
         because it is a background, not a shape.
         Wells, washes and the mark only. Never text, never a border. ---- */
  --indigo:      #B01A7A;
  --indigo-wash: rgba(122, 16, 96, .22);

  /* ---- shadow tint · matched to the ground, so shadows deepen the teal
         rather than greying it out. Never untinted grey. ---- */
  --shade: 3, 14, 20;

  /* ---- states ---- */
  --ok:   #3FBF8F;
  --warn: #E5B54A;

  /* ---- families ---- */
  --f-display: "Clash Display", "Helvetica Neue", Arial, sans-serif;
  --f-body: "Satoshi", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  /* ---- type scale ---- */
  --t-display: clamp(3.25rem, 8.2vw, 7rem);
  --t-h1:      clamp(2.6rem, 5.6vw, 4.5rem);
  --t-h2:      clamp(2.1rem, 4.2vw, 3.4rem);
  --t-h3:      clamp(1.35rem, 2.1vw, 1.75rem);
  --t-h4:      1.0625rem;
  --t-lead:    clamp(1.05rem, 1.5vw, 1.25rem);
  --t-body:    1.0625rem;
  --t-sm:      .9375rem;
  --t-micro:   .8125rem;
  --t-stat:    clamp(3rem, 6vw, 5rem);

  /* ---- spacing · 8px base with two half-steps ---- */
  --s-1: 4px;    --s-2: 8px;    --s-3: 12px;  --s-4: 16px;
  --s-5: 24px;   --s-6: 32px;   --s-7: 48px;  --s-8: 64px;
  --s-9: 88px;   --s-10: 120px; --s-11: 160px;

  /* compact by default: 140px top+bottom was 280px between every section */
  --section-y: clamp(40px, 4vw, 72px);
  --gutter:    clamp(20px, 5vw, 80px);
  --maxw:      1600px;
  --maxw-wide: 1800px;
  /* deliberately tight: images sit close enough to read as one field */
  --gap:       clamp(12px, 1.4vw, 20px);

  /* ---- radius · carries hierarchy ---- */
  --r-xs: 4px;
  --r-sm: 8px;
  --r-md: 14px;
  --r-lg: 20px;
  --r-pill: 999px;

  /* ---- motion ---- */
  --e-out:    cubic-bezier(.22, 1, .36, 1);
  --e-in-out: cubic-bezier(.65, 0, .35, 1);
  --e-snap:   cubic-bezier(.34, 1.3, .64, 1);

  --d-1: 160ms;  --d-2: 320ms;  --d-3: 420ms;  --d-4: 620ms;  --d-5: 1100ms;

  /* ---- shell metrics · read by shell.js and by the hero ---- */
  --announce-h:  36px;
  --hdr-h:       78px;
  --hdr-h-stuck: 62px;
}

@media (max-width: 559px) {
  :root { --announce-h: 0px; }
}

/* announcement dismissed · in-memory for the session only.
   Persistence across visits is deliberately not handled here — it becomes a
   WordPress/cookie-consent concern in Phase 2. See shell.js. */
html.announce-closed { --announce-h: 0px; }

@media (max-width: 1079px) {
  :root { --hdr-h: 64px; --hdr-h-stuck: 58px; }
}


/* ===== 03 · BASE TYPOGRAPHY =========================================== */

body {
  font-family: var(--f-body);
  font-size: var(--t-body);
  line-height: 1.66;
  color: var(--bone-2);
  background: var(--ink-900);
  padding-block-start: var(--announce-h);
  transition: padding-block-start var(--d-3) var(--e-out);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;
}

/* the single global grain overlay · never animated, never duplicated */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background-image: url(../assets/images/noise.png);
  background-size: 180px;
  opacity: .035;
  mix-blend-mode: overlay;
}

h1, h2, h3 {
  font-family: var(--f-display);
  text-wrap: balance;
}

/* Headings carry the brand lime. h3 is held back at bone deliberately: it is
   the card and block title, and a lime h2 above a lime h3 inside the same
   card flattens two levels into one. Legal prose keeps its own bone h2 —
   a green heading every few paragraphs of a contract is noise, and it would
   also drain the meaning out of the magenta "still to be confirmed" blocks
   sitting between them. */
h1, h2 { color: var(--azure); }
h3     { color: var(--bone); }

h1 {
  font-size: var(--t-display);
  font-weight: 600;
  line-height: .90;
  letter-spacing: -.038em;
}

h2 {
  font-size: var(--t-h2);
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: -.026em;
}

h3 {
  font-size: var(--t-h3);
  font-weight: 500;
  line-height: 1.14;
  letter-spacing: -.016em;
}

strong, b { font-weight: 700; color: var(--bone); }

.lead {
  font-size: var(--t-lead);
  line-height: 1.58;
  color: var(--bone-dim);
  max-inline-size: 54ch;
  text-wrap: pretty;
}

/* ===== 04 · LAYOUT ==================================================== */

.container {
  max-inline-size: var(--maxw);
  padding-inline: var(--gutter);
  margin-inline: auto;
  inline-size: 100%;
}

/* vertical rhythm is declared HERE and nowhere else */
.section { padding-block: var(--section-y); }

.section--alt    { background: var(--ink-850); }
.section--seamed { border-block: 1px solid var(--line); }

.grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--gap);
}

.col-1 { grid-column: span 1; }
.col-2 { grid-column: span 2; }
.col-3 { grid-column: span 3; }
.col-4 { grid-column: span 4; }

@media (min-width: 768px) {
  .grid { grid-template-columns: repeat(8, minmax(0, 1fr)); }
  .col-md-1 { grid-column: span 1; }
  .col-md-2 { grid-column: span 2; }
  .col-md-3 { grid-column: span 3; }
  .col-md-4 { grid-column: span 4; }
  .col-md-5 { grid-column: span 5; }
  .col-md-6 { grid-column: span 6; }
  .col-md-7 { grid-column: span 7; }
  .col-md-8 { grid-column: span 8; }
}

@media (min-width: 1080px) {
  .grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .col-lg-1  { grid-column: span 1; }
  .col-lg-2  { grid-column: span 2; }
  .col-lg-3  { grid-column: span 3; }
  .col-lg-4  { grid-column: span 4; }
  .col-lg-5  { grid-column: span 5; }
  .col-lg-6  { grid-column: span 6; }
  .col-lg-7  { grid-column: span 7; }
  .col-lg-8  { grid-column: span 8; }
  .col-lg-9  { grid-column: span 9; }
  .col-lg-10 { grid-column: span 10; }
  .col-lg-11 { grid-column: span 11; }
  .col-lg-12 { grid-column: span 12; }
}


/* ===== 05 · SHARED UTILITIES ========================================== */

/* The three-layer depth recipe from the design system is applied directly on
   the four surfaces that use it (.card, .hero__panel, .atmos__media,
   .analytics__panel) rather than as a standalone .surface class, so there is
   no utility here that nothing consumes.

   THE SEAM · bleeds in from the left viewport edge.
   Used exactly three times: hero line 2, closing CTA heading, footer logo. */
.seam {
  display: block;
  block-size: 1px;
  inline-size: calc(var(--gutter) + 120px);
  margin-inline-start: calc(-1 * var(--gutter));
  background: linear-gradient(90deg, transparent, var(--line-hi) 30%, var(--line-hi));
}

/* used exactly twice on the homepage */
.eyebrow {
  display: block;
  font-size: var(--t-micro);
  font-weight: 500;
  line-height: 1.45;
  letter-spacing: .01em;
  color: var(--bone-dim);
  margin-block-end: var(--s-5);
}

/* Scroll-in reveal · section headings + first-level children only.
   Uses the independent `translate` property, never `transform`. A reveal on a
   .card would otherwise win on specificity and kill the card's hover lift and
   the raised pricing panel. translate composes with transform instead. */
html.js .reveal {
  opacity: 0;
  translate: 0 12px;
  transition:
    opacity 520ms var(--e-out),
    translate 520ms var(--e-out);
  transition-delay: calc(var(--i, 0) * 60ms);
}

html.js .reveal.is-revealed {
  opacity: 1;
  translate: none;
}

/* the orchestrated six-beat load · hero + shell only, fired once by home.js.
   Nothing else on the page animates on load. --b carries the beat delay. */
html.js .beat {
  opacity: 0;
  translate: 0 16px;
  transition:
    opacity var(--d-4) var(--e-out) var(--b, 0ms),
    translate var(--d-4) var(--e-out) var(--b, 0ms),
    scale var(--d-4) var(--e-out) var(--b, 0ms);
}

html.js .beat--down  { translate: 0 -100%; }
html.js .beat--fade  { translate: none; }
html.js .beat--line  { translate: 0 100%; }
html.js .beat--panel { translate: none; scale: .985; transition-duration: var(--d-5); }

html.js.is-loaded .beat { opacity: 1; translate: none; scale: none; }


/* ===== 06 · ACCESSIBILITY UTILITIES =================================== */

.sr-only {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip {
  position: fixed;
  inset-block-start: var(--s-2);
  inset-inline-start: var(--s-2);
  z-index: 200;
  padding: var(--s-3) var(--s-5);
  border-radius: var(--r-sm);
  background: var(--azure);
  color: var(--ink-950);
  font-size: var(--t-sm);
  font-weight: 700;
  transform: translateY(calc(-100% - var(--s-4)));
  transition: transform var(--d-2) var(--e-out);
}

.skip:focus-visible { transform: none; }


/* ===== 07 · REDUCED MOTION ============================================ */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  /* marquees become static, horizontally scrollable strips */
  .marquee__track {
    animation: none !important;
    transform: none !important;
  }
  .marquee {
    overflow-x: auto !important;
    -webkit-mask-image: none !important;
    mask-image: none !important;
  }
}


/* ===== 08 · PRINT ===================================================== */
/* Reveals below the fold never fire their observer when the page is printed,
   so everything that is opacity-gated is forced visible here. Placed last so
   it wins on source order without needing !important. */
@media print {
  html.js .reveal,
  html.js .beat {
    opacity: 1;
    translate: none;
    scale: none;
  }
  .topstack,
  .drawer,
  body::after { display: none; }
  body { padding-block-start: 0; }
}
