/* Digital Jungle — design tokens and shared primitives
   Source: Visual Guide — Digital Jungle (Graphic guidelines 2026)
           DIGITAL-JUNGLE-V2-PLAN.md §2 (palette, type, shape) and §7 (motion)

   The palette and type scale are also declared in theme.json so the block editor
   offers them by name. These custom properties are the same values, available to
   hand-written CSS and to Kadence's custom-CSS fields. */

:root {
  /* Primary — teal and purple anchor every layout */
  --dj-purple: #8A66B0;
  --dj-green: #67ACAC;

  /* Secondary — public toolkit accents */
  --dj-yellow: #FECB00;
  --dj-red: #D20069;          /* danger only, used sparingly */
  --dj-blue: #00BBE1;
  --dj-orchid: #CD6DB3;
  --dj-forest: #015B37;
  --dj-bright-green: #6CB58B;

  /* Neutrals */
  --dj-black: #000000;
  --dj-white: #FFFFFF;
  --dj-off-white: #F4F1EC;

  /* Opacity steps — 80 / 50 / 20. Use these for depth instead of new tints. */
  --dj-opacity-strong: 0.8;
  --dj-opacity-mid: 0.5;
  --dj-opacity-soft: 0.2;

  /* The only sanctioned gradients */
  --dj-gradient: linear-gradient(135deg, var(--dj-green), var(--dj-purple));
  --dj-gradient-vertical: linear-gradient(180deg, var(--dj-purple), var(--dj-green));
  --dj-gradient-120: linear-gradient(120deg, var(--dj-green), var(--dj-purple));
  --dj-gradient-protect: linear-gradient(180deg, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.55));

  /* Type */
  --dj-font-display: 'Onest', Arial, sans-serif;
  --dj-font-body: 'Inter', Arial, sans-serif;

  /* Type scale.
     NOTE — deviation from ds/tokens/typography.css, deliberate:
     the token file sets body 15px and caption 13px, but both CLAUDE-CODE-TASK.md
     and V2-PLAN §8 require "body text never below 16px". Two authoritative
     sources beat the token file, and this is a WCAG commitment on an EU-funded
     project, so the floor wins: body 16px, smallest supporting text 14px. */
  --dj-text-small: 0.875rem;                          /* 14px — labels, meta   */
  --dj-text-body: 1rem;                               /* 16px — body floor     */
  --dj-text-body-lg: 1.125rem;                        /* 18px                  */
  --dj-text-title: 1.3125rem;                         /* 21px                  */
  --dj-text-headline: clamp(1.5rem, 2.4vw, 1.875rem); /* 24–30px               */
  --dj-text-page-title: clamp(2.125rem, 4.6vw, 3.625rem);/* 34–58px — h1 of the
                                                         inner pages. Only the
                                                         home hero goes bigger. */
  --dj-text-display: clamp(1.875rem, 3.6vw, 2.875rem);/* 30–46px               */
  --dj-text-display-xl: clamp(3.25rem, 9vw, 8rem);    /* 52–128px — hero only  */

  --dj-leading-body: 1.55;
  --dj-leading-display: 1.06;
  --dj-tracking-display: -0.01em;
  --dj-weight-body: 400;
  --dj-weight-light: 300;
  --dj-weight-emphasis: 600;

  /* Shape — flat system, no shadows anywhere */
  --dj-radius-photo: 12px;
  --dj-radius-card: 12px;
  --dj-radius-pill: 999px;
  --dj-border-sweep: 2px solid var(--dj-white);

  /* Spacing, 4px step */
  --dj-space-1: 4px;
  --dj-space-2: 8px;
  --dj-space-3: 12px;
  --dj-space-4: 16px;
  --dj-space-5: 24px;
  --dj-space-6: 32px;
  --dj-space-7: 48px;
  --dj-space-8: 64px;
  /* Three section rhythms, because the design uses three — not one. Applying
     the largest everywhere made About's narrative 38 % taller than the approved
     layout and the Toolkit filter strip five times its height. */
  --dj-space-section: clamp(64px, 8vw, 110px);      /* heaviest: home sections */
  --dj-space-section-md: clamp(56px, 8vw, 96px);    /* narrative, teasers      */
  --dj-space-section-sm: clamp(48px, 6vw, 80px);    /* lighter strips          */

  --dj-measure: 1240px;

  /* Motion — V2-PLAN §7. One vocabulary, applied consistently. */
  --dj-ease-enter: cubic-bezier(0.2, 0.8, 0.2, 1);
  --dj-ease-state: cubic-bezier(0.4, 0, 0.2, 1);
  --dj-duration-micro: 200ms;
  --dj-duration-element: 400ms;
  --dj-duration-hero: 900ms;
  --dj-marquee-duration: 40s;
  --dj-orbit-duration: 60s;

  /* Sweep geometry. --dj-sweep (the mask image) is injected by functions.php. */
  --dj-sweep-aspect: 323.69 / 166.04;
}

/* Material Symbols — functional icon cues only (arrows, chevrons, the consent
   shield). Subset to the eight glyphs this build actually uses: the full family
   is 3.78 MB, this is 4.9 KB. Referenced by codepoint rather than by ligature
   name, because keeping the ligature table is what made the subset large.

   Self-hosted like the text faces: no request leaves for Google. */
@font-face {
  font-family: 'Material Symbols Outlined';
  src: url('../fonts/MaterialSymbols-subset.woff2') format('woff2');
  font-weight: 100 700;
  font-style: normal;
  font-display: block;
}

.material-symbols-outlined,
[class*="__icon"] {
  /* The family itself. Declaring @font-face and the variation axes but never
     the font-family left every icon rendering in Inter — the glyphs are in the
     Private Use Area, so they came out as nothing at all rather than as a
     visible error. The arrows only worked because their own rule repeated it. */
  font-family: 'Material Symbols Outlined';
  font-weight: normal;
  font-style: normal;
  font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  white-space: nowrap;
  direction: ltr;
  -webkit-font-feature-settings: 'liga';
  -webkit-font-smoothing: antialiased;
}

/* ---------------------------------------------------------------- primitives */

/* The Sweep — the headline holder. Always anchored to a corner or edge of its
   composition, never floating in the middle (design-system rule). Recolour by
   setting `background`; the element is masked to the brand shape. */
.dj-sweep {
  aspect-ratio: var(--dj-sweep-aspect);
  -webkit-mask-image: var(--dj-sweep);
  mask-image: var(--dj-sweep);
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}

/* The Hero Element — the diamond from the compass centre. Bullet marker,
   section divider, progress dot, image frame. */
.dj-diamond {
  display: inline-block;
  flex: none;
  width: 10px;
  height: 10px;
  background: currentColor;
  transform: rotate(45deg);
}

/* Scroll containers that carry their own affordance (arrows, dots, drag). */
.dj-hidescroll {
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.dj-hidescroll::-webkit-scrollbar {
  display: none;
}

/* Touch targets — brief §8 requires 44px minimum on every control. */
.dj-control {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  border-radius: var(--dj-radius-pill);
  cursor: pointer;
  background: none;
  transition: color var(--dj-duration-micro) var(--dj-ease-state),
              background-color var(--dj-duration-micro) var(--dj-ease-state),
              border-color var(--dj-duration-micro) var(--dj-ease-state);
}

/* Visible focus everywhere — keyboard reachability is an acceptance criterion. */
:where(a, button, input, textarea, select, [tabindex]):focus-visible {
  outline: 3px solid var(--dj-purple);
  outline-offset: 2px;
}

/* ------------------------------------------------------------------- motion */

/* Entrance: opacity 0→1 + translateY 16px→0, fired once by dj.js at 15%
   visibility. Elements start visible and are only hidden once JS confirms it
   can animate them, so a failed script never leaves the page blank. */
.dj-js .dj-reveal {
  opacity: 0;
  transform: translateY(16px);
}

.dj-js .dj-reveal.is-visible {
  opacity: 1;
  transform: none;
  transition: opacity var(--dj-duration-element) var(--dj-ease-enter),
              transform var(--dj-duration-element) var(--dj-ease-enter);
  transition-delay: var(--dj-stagger, 0ms);
}

@keyframes dj-wipe {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}

@keyframes dj-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

@keyframes dj-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

@keyframes dj-pulse-y {
  0%, 100% { transform: translateY(0);   opacity: 0.6; }
  50%      { transform: translateY(6px); opacity: 1; }
}

/* Reduced motion — V2-PLAN §7. Animations collapse, marquees stop, parallax is
   disabled by dj.js, counters jump to their final value. Nothing disappears. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  .dj-js .dj-reveal {
    opacity: 1;
    transform: none;
  }
}

/* The motionIntensity prop from the design, as a body class the editor can set:
   dj-motion-reduced trims continuous motion, dj-motion-off stops all of it. */
.dj-motion-off *,
.dj-motion-off *::before,
.dj-motion-off *::after {
  animation: none !important;
  transition: none !important;
}

.dj-motion-off .dj-reveal,
.dj-motion-reduced .dj-reveal {
  opacity: 1;
  transform: none;
}

.dj-motion-reduced .dj-marquee-track,
.dj-motion-reduced .dj-orbit {
  animation: none !important;
}

/* ─────────────────────────────────────────────────────────────────────────
   Kadence bridge

   Kadence is a classic theme: its Customizer CSS, not theme.json, is the
   authority for body type and colour, and every rule it writes resolves
   through its own `--global-*` variables. Rebinding those variables here is
   what makes the whole theme — buttons, header, footer, Kadence Blocks —
   follow the Digital Jungle system instead of Kadence's default blue/grey.

   Slot semantics are Kadence's own: 1–2 accent, 3–6 a dark→light text ramp,
   7–9 backgrounds. Values are the ones the approved v2 markup actually uses,
   including the 20/50/80 % opacity steps the design system sanctions.
   ───────────────────────────────────────────────────────────────────────── */
:root {
  --global-palette1: var(--dj-purple);            /* accent — links, buttons  */
  --global-palette2: var(--dj-green);             /* accent hover             */
  --global-palette3: var(--dj-black);             /* headings                 */
  --global-palette4: #1a1a1a;                     /* body copy                */
  /* Slots 5 and 6 look like border colours by their position in the ramp, but
     Kadence uses both almost exclusively as text — blockquote cites, input
     text, placeholders, search icons — and never for borders. Anything below
     55 % black fails WCAG AA on white (0.5 → 3.98:1, 0.2 → 1.61:1), so these
     two are picked for contrast, not for how they would look as a hairline.
     Borders come from the patterns themselves. */
  --global-palette5: rgba(0, 0, 0, 0.8);          /* medium text — 12.6:1     */
  --global-palette6: rgba(0, 0, 0, 0.55);         /* muted text —   4.8:1     */
  --global-palette7: var(--dj-off-white);         /* light surface            */
  --global-palette8: var(--dj-white);
  --global-palette9: var(--dj-white);

  --global-palette-highlight: var(--dj-purple);
  --global-palette-btn: var(--dj-white);
  --global-palette-btn-bg: var(--dj-purple);
  --global-palette-btn-hover: var(--dj-white);
  --global-palette-btn-bg-hover: var(--dj-green);

  --global-body-font-family: var(--dj-font-body);
  --global-heading-font-family: var(--dj-font-display);

  /* The v2 layouts are built on a 1240px measure; Kadence ships 1290px. */
  --global-content-width: 1240px;
}

/* Kadence writes these two as literal values rather than through a variable,
   so they need a real rule. This sheet loads after kadence-global, so equal
   specificity is enough — no !important needed. */
body,
input,
select,
optgroup,
textarea {
  font-family: var(--dj-font-body);
  font-size: var(--dj-text-body);
  line-height: 1.55;
  color: #1a1a1a;
}

/* Family only. Heading colour already resolves through --global-palette3, and
   pinning it here would put a real selector in the way of every white heading
   on the dark and purple sections — of which the design has many. */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--dj-font-display);
}

/* ── Kadence overrides that variables cannot reach ────────────────────────
   Two Kadence rules are written as literal declarations rather than through
   `--global-*`, so rebinding the variables does not touch them. Both break a
   design-system rule, so they need real selectors. This sheet loads after
   kadence-global, so matching specificity is enough — no !important. */

/* Buttons are pills. theme.json does emit a 999px rule, but WordPress wraps
   it in :where() — zero specificity — and Kadence's class selector wins. */
button,
.button,
.wp-block-button__link,
.wp-element-button,
input[type="button"],
input[type="reset"],
input[type="submit"] {
  border-radius: var(--dj-radius-pill);
  font-family: var(--dj-font-display);
  font-weight: var(--dj-weight-emphasis);
}

/* The system is flat: no drop shadows or glows anywhere (V2-PLAN §1).
   Kadence gives post and page cards a 15px drop shadow by default. */
.entry.single-entry,
.entry.loop-entry,
.entry-content-wrap .entry {
  box-shadow: none;
}
