/* ============================================================================
   AK BRAND DEVELOPMENT STUDIO — design system for WordPress
   ----------------------------------------------------------------------------
   Ported from the React prototype with no build step and no Tailwind: these
   are plain custom properties and plain CSS, so the child theme can be
   installed as a ZIP and edited in place.

   Loaded after Zeyna's own stylesheet (see inc/enqueue.php), so it wins on
   equal specificity without a single !important.
   ==========================================================================*/

:root {

  /* ---- Type families -------------------------------------------------- */
  /* Fraunces over Instrument Serif / PP Editorial New deliberately: those two
     are the 2026 shorthand for "no type budget", and Fraunces carries real
     axes (opsz 9-144, SOFT, WONK) that Instrument Serif does not have, which
     is what makes the scroll-driven type in base.css possible at all.
     Bricolage Grotesque over Inter/Geist for the same reason: an irregular
     grotesque with opsz + wdth axes, not the default everyone ships. */
  --font-display: "Fraunces", "Fraunces Fallback", "Times New Roman", serif;
  --font-sans: "Bricolage Grotesque", "Bricolage Fallback", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "Martian Mono", ui-monospace, "SF Mono", monospace;

  /* ---- Brand orange ---------------------------------------------------
     Source: #f37021 = oklch(0.6924 0.1812 46.21). Chroma clamped to sRGB
     at every step so the ramp never clips on standard displays.
     The ramp DRIFTS IN HUE, on purpose: tints move toward yellow-cream
     (H 62) and shades toward rust-red (H 27), the way real pigment does. A
     ramp holding one hue at every step is the unmistakable signature of an
     auto-generated palette.

     Contrast, measured against this site's own surfaces — paper #f9f6f2 and
     warm ink #100d0a — not against generic white and black:

       brand-500 on paper  = 2.73:1  FAILS 1.4.11 non-text (needs 3.0), by 0.27.
                                     So the brand orange is never a mark, a
                                     rule or a focus ring on the light theme.
       brand-600 on paper  = 3.49:1  PASSES 1.4.11 → accent MARKS in light mode
       brand-700 on paper  = 4.80:1  PASSES AA text → accent TEXT in light mode
       brand-500 on ink    = 6.60:1  PASSES AA text → accent marks + text on dark
       brand-400 on ink    = 8.43:1  used for SMALL accent text on dark: 500
                                     technically passes WCAG but APCA rates it
                                     Lc-46, which wants ~39px at weight 400.
                                     WCAG over-rewards saturated mid-luminance
                                     colours on dark grounds; small orange
                                     labels genuinely glare at 500.
       ink on brand-500    = 6.60:1  PASSES AA → orange fills take INK type.
                                     White on orange is 2.94:1 and fails three
                                     thresholds at once; it is also what nearly
                                     every orange brand ships.
     -------------------------------------------------------------------- */
  --color-brand-50:  oklch(0.972 0.0179 62);     /* #fff3ea */
  --color-brand-100: oklch(0.940 0.0380 60);     /* #ffe6d2 */
  --color-brand-200: oklch(0.885 0.0729 57);     /* #ffceab */
  --color-brand-300: oklch(0.822 0.1080 54);     /* #fcb281 */
  --color-brand-400: oklch(0.755 0.1580 50);     /* #fd8e49 — accent TEXT on ink, 8.43:1 */
  --color-brand-500: oklch(0.6924 0.1812 46.21); /* #f37021 ← THE brand colour, identical in both modes */
  --color-brand-600: oklch(0.630 0.1760 42);     /* #dd5b1e — accent MARKS on paper, 3.49:1 */
  --color-brand-700: oklch(0.552 0.1550 38);     /* #ba4923 — accent TEXT on paper, 4.80:1 */
  --color-brand-800: oklch(0.468 0.1300 34);     /* #953823 */
  --color-brand-900: oklch(0.372 0.0980 30);     /* #6b281f */
  --color-brand-950: oklch(0.268 0.0680 27);     /* #411613 */

  /* ---- Warm neutral ramp ("ink") --------------------------------------
     Hue 60 at chroma 0.005–0.008: warm enough to sit with orange, cold
     enough never to read as brown. A blue-black would fight the accent. */
  --color-ink-950: oklch(0.162 0.008 58);         /* #100d0a — warm ink, never #000 */
  --color-ink-900: oklch(0.185 0.007 60);         /* #151210 */
  --color-ink-850: oklch(0.225 0.008 60);         /* #1f1b18 */
  --color-ink-800: oklch(0.275 0.008 60);         /* #2b2724 */
  --color-ink-700: oklch(0.360 0.008 60);         /* #403c39 */
  --color-ink-600: oklch(0.470 0.008 60);         /* #5e5a56 */
  --color-ink-500: oklch(0.580 0.008 60);         /* #7e7976 */
  --color-ink-400: oklch(0.680 0.007 60);         /* #9c9794 */
  --color-ink-300: oklch(0.780 0.006 60);         /* #bab6b4 */
  --color-ink-200: oklch(0.870 0.005 60);         /* #d7d3d1 */
  --color-ink-100: oklch(0.930 0.005 60);         /* #eae7e5 */
  --color-paper:     oklch(0.975 0.006 70);       /* #f9f6f2 */
  --color-paper-dim: oklch(0.950 0.007 70);       /* #f2eee9 */

  /* ---- No fourth colour ------------------------------------------------
     A cold "data" tone was drafted here and then cut. The palette is warm
     ink, warm paper and #f37021 — three colours, held hard. The warmth is
     already what separates this from the greyscale-plus-one-accent look that
     every AI-era product site now shares; adding a desaturated blue would
     quietly put it back. Data is separated by TYPEFACE (Martian Mono) and by
     position, not by hue. */

  /* ---- Motion tokens ---------------------------------------------------
     One vocabulary for the whole site. Every animation picks from here. */
  --ease-cut:    cubic-bezier(0.16, 1, 0.30, 1);    /* expo-out: reveals   */
  --ease-thread: cubic-bezier(0.65, 0.05, 0.36, 1); /* in-out: the seam    */
  --ease-snap:   cubic-bezier(0.34, 1.56, 0.64, 1); /* overshoot: HUD pins */
  --ease-drape:  cubic-bezier(0.22, 0.61, 0.36, 1); /* soft settle: fabric */

  /* spring-ui: stiffness 320, damping 26, mass 1 — settles in 531ms */
  --ease-spring-ui: linear(0.0000, 0.0210, 0.0754, 0.1520, 0.2418, 0.3377, 0.4341, 0.5272, 0.6140, 0.6928, 0.7627, 0.8232, 0.8744, 0.9169, 0.9512, 0.9782, 0.9988, 1.0139, 1.0244, 1.0311, 1.0347, 1.0360, 1.0355, 1.0337, 1.0311, 1.0279, 1.0245, 1.0210, 1.0176, 1.0144, 1.0115, 1.0090, 1.0067, 1.0048, 1.0032, 1.0019, 1.0009, 1.0002, 0.9996, 0.9992, 0.9989, 0.9988, 0.9987, 0.9987, 0.9988);
  --dur-spring-ui: 531ms;
  /* spring-panel: stiffness 200, damping 24, mass 1 — settles in 576ms */
  --ease-spring-panel: linear(0.0000, 0.0154, 0.0555, 0.1125, 0.1801, 0.2535, 0.3290, 0.4038, 0.4759, 0.5440, 0.6070, 0.6646, 0.7165, 0.7627, 0.8034, 0.8389, 0.8696, 0.8958, 0.9180, 0.9366, 0.9521, 0.9648, 0.9751, 0.9833, 0.9899, 0.9949, 0.9988, 1.0016, 1.0036, 1.0050, 1.0059, 1.0063, 1.0065, 1.0064, 1.0062, 1.0058, 1.0054, 1.0049, 1.0044, 1.0039, 1.0034, 1.0030, 1.0026, 1.0022, 1.0019);
  --dur-spring-panel: 576ms;

  --duration-instant: 120ms;
  --duration-quick:   240ms;
  --duration-base:    480ms;
  --duration-slow:    820ms;
  --duration-reveal: 1200ms;

  /* ---- Layout ---------------------------------------------------------- */
  --spacing-gutter: 1.5rem;
  --radius-seam: 2px;    /* the house radius: almost none. Atelier, not app. */
}

/* ============================================================================
   SEMANTIC THEME LAYER
   Two designed modes, not one derived from the other:
     ATELIER (light) — the workroom. Paper, chalk lines, daylight.
     RUNWAY  (dark)  — the show. Ink, spotlight, the accent alive.
   Every colour below is defined on bare :root first, so no value exists
   only inside a media query or attribute selector.
   ==========================================================================*/

:root {
  color-scheme: light;

  --bg:            var(--color-paper);
  --bg-sunk:       var(--color-paper-dim);
  --bg-raised:     oklch(1 0 0);
  --text:          var(--color-ink-950);
  --text-muted:    var(--color-ink-600);
  --text-faint:    oklch(0.51 0.008 60);   /* 4.6:1 — carries real text */
  --rule:          oklch(0.145 0.006 60 / 0.14);
  --rule-strong:   oklch(0.145 0.006 60 / 0.32);

  /* The accent splits by role. This split is the whole reason the palette
     survives both modes: the FILL is always true #f37021, the TEXT is not. */
  --accent-fill:   var(--color-brand-500);  /* surfaces, always true brand */
  --accent-on:     var(--color-ink-950);    /* what sits ON a fill: 7.15:1 */
  --accent-text:   var(--color-brand-700);  /* orange as type: 4.80:1     */
  --accent-line:   var(--color-brand-600);  /* marks/rules/focus: 3.49:1   */
  --accent-glow:   oklch(0.6924 0.1812 46.21 / 0.16);

  --grain-opacity: 0.030;
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --bg:            var(--color-ink-950);
  --bg-sunk:       oklch(0.115 0.005 60);
  --bg-raised:     var(--color-ink-900);
  --text:          var(--color-paper);
  --text-muted:    var(--color-ink-400);
  --text-faint:    oklch(0.60 0.008 60);   /* 4.9:1 on ink */
  --rule:          oklch(0.975 0.006 70 / 0.13);
  --rule-strong:   oklch(0.975 0.006 70 / 0.28);

  --accent-fill:   var(--color-brand-500);
  --accent-on:     var(--color-ink-950);
  --accent-text:   var(--color-brand-400);  /* 8.43:1 — small labels read  */
  --accent-line:   var(--color-brand-500);  /* 6.60:1 on ink — marks fine  */
  --accent-glow:   oklch(0.6924 0.1812 46.21 / 0.26);

  --grain-opacity: 0.045;
}

/* System preference only decides when the user has expressed no choice. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not([data-theme="dark"]) {
    color-scheme: dark;
    --bg:          var(--color-ink-950);
    --bg-sunk:     oklch(0.115 0.005 60);
    --bg-raised:   var(--color-ink-900);
    --text:        var(--color-paper);
    --text-muted:  var(--color-ink-400);
    --text-faint:  oklch(0.60 0.008 60);
    --rule:        oklch(0.975 0.006 70 / 0.13);
    --rule-strong: oklch(0.975 0.006 70 / 0.28);
    --accent-text: var(--color-brand-400);
    --accent-line: var(--color-brand-500);
    --accent-glow: oklch(0.6924 0.1812 46.21 / 0.26);
    --grain-opacity: 0.045;
  }
}


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

html {
  /* Lenis drives scrolling; this is the no-JS / reduced-motion fallback. */
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.5;
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  transition: background-color 620ms var(--ease-drape),
              color 620ms var(--ease-drape);
}

/* Theme swap should not animate every descendant — only the two properties
   that actually change the room. Everything else flips instantly. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  body { transition: none; }
}

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

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

/* Lenis */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: hidden; }

/* Screen-reader-only, still focusable */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: 1rem; top: -100%; z-index: 200;
  font-family: var(--font-mono);
  font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.1em;
  transition: top 200ms var(--ease-cut);
}
/* The whole visual treatment sits on :focus — (0,2,0), same specificity as
   Zeyna's own .screen-reader-text:focus, and this sheet loads after the
   parent, so the house style wins instead of the parent's grey box. */
.skip-link:focus {
  top: 1rem; left: 1rem;
  background: var(--accent-fill); color: var(--accent-on);
  padding: 0.75rem 1.25rem;
  box-shadow: none; border-radius: 0;
}

/* ---------------------------------------------------------------------------
   CUT TEXT — the house headline reveal (see CutText.tsx)
   ------------------------------------------------------------------------ */
.ak-cut { display: block; }

.ak-cut-line {
  display: block;
  position: relative;
  overflow: hidden;
}

/* Once the reveal has finished, the split is dismantled: the duplicate half is
   removed and both the clip and the line's overflow are released. This matters
   for a specific typographic reason — display type here is set at ~0.9 leading,
   so descenders (g, y, p) and the italic f sit OUTSIDE the line box, and
   clip-path clips to the element's own box no matter what padding a parent
   carries. Clipping is therefore only ever allowed to exist while something is
   actually moving; the resting state is plain, unclipped text. */
.ak-cut-line[data-cut-settled] { overflow: visible; }

.ak-cut-half {
  display: block;
  /* Deliberately no `will-change`. In a static selector it permanently
     promotes every match to its own compositor layer (roughly w x h x 4 bytes
     of GPU memory each, on every headline on the page). GSAP's default
     force3D:'auto' promotes for the duration of the tween and un-promotes
     afterwards, which is what we actually want. */
}
/* Each half shows exactly one side of the line's horizontal midline. The
   bottom copy is pulled back up over the top copy so the two read as one. */
.ak-cut-half--top    { clip-path: inset(0 0 50% 0); }
.ak-cut-half--bottom { clip-path: inset(50% 0 0 0); margin-top: -1lh; }

.ak-cut-blade {
  position: absolute;
  left: 0; right: 0; top: 50%;
  height: 1px;
  background: var(--accent-line);
  transform: scaleX(0);
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  /* Both halves carry the full line, so unclipping BOTH would render it
     twice. Keep the top copy whole and drop the duplicate. */
  .ak-cut-half--top { clip-path: none; }
  .ak-cut-half--bottom { display: none; }
  .ak-cut-blade { display: none; }
}

/* ---------------------------------------------------------------------------
   MEASURE FRAME — tech-pack annotations (see MeasureFrame.tsx)
   ------------------------------------------------------------------------ */
.ak-tick {
  position: absolute;
  width: 11px; height: 11px;
  border: 0 solid var(--accent-line);
}
.ak-tick--tl { top: -1px; left: -1px;  border-top-width: 1px; border-left-width: 1px; }
.ak-tick--tr { top: -1px; right: -1px; border-top-width: 1px; border-right-width: 1px; }
.ak-tick--bl { bottom: -1px; left: -1px;  border-bottom-width: 1px; border-left-width: 1px; }
.ak-tick--br { bottom: -1px; right: -1px; border-bottom-width: 1px; border-right-width: 1px; }

.ak-dim {
  position: absolute;
  background: var(--accent-line);
  opacity: 0.55;
}
.ak-dim--top {
  top: -13px; left: 0; right: 0; height: 1px;
  transform-origin: left center;
}

.ak-dim-label {
  position: absolute;
  top: -13px; left: 50%;
  translate: -50% -50%;
  padding: 0 0.5em;
  background: var(--bg);
  color: var(--accent-text);
  font-family: var(--font-mono);
  font-size: 0.5625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  /* A caption sits ON a 1px dimension rule, so it must stay one line — but an
     unbounded nowrap label is wider than the frame it annotates and drags the
     whole document with it. Cap it to the frame and ellipsise. */
  white-space: nowrap;
  max-width: calc(100% - 2rem);
  overflow: hidden;
  text-overflow: ellipsis;
}

.ak-callout {
  position: absolute;
  display: flex;
  align-items: center;
  gap: 0.4em;
  font-family: var(--font-mono);
  font-size: 0.5625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  background: var(--bg);
  border: 1px solid var(--rule-strong);
  padding: 0.25em 0.5em;
  line-height: 1;
}
.ak-callout__key   { color: var(--text-faint); font-weight: 400; }
.ak-callout__value { color: var(--accent-text); font-weight: 700; font-variant-numeric: tabular-nums; }

/* Leader line runs from the callout back to the edge it annotates. */
.ak-callout__leader { position: absolute; background: var(--accent-line); opacity: 0.6; }

.ak-callout--right  { right: 12px; translate: 0 -50%; }
.ak-callout--right  .ak-callout__leader { right: 100%; top: 50%; width: 12px; height: 1px; }
.ak-callout--left   { left: 12px; translate: 0 -50%; }
.ak-callout--left   .ak-callout__leader { left: 100%; top: 50%; width: 12px; height: 1px; }
.ak-callout--bottom { top: 100%; translate: -50% 14px; }
.ak-callout--bottom .ak-callout__leader { bottom: 100%; left: 50%; height: 14px; width: 1px; }
.ak-callout--top    { bottom: 100%; translate: -50% -14px; }
.ak-callout--top    .ak-callout__leader { top: 100%; left: 50%; height: 14px; width: 1px; }

@media (max-width: 640px) {
  /* Leader lines stop earning their space once the callout is this close to
     the edge it annotates. */
  .ak-callout__leader { display: none; }
  .ak-callout {
    font-size: 0.5rem;
    /* A long value ("LDN · PAR · DXB") held on one line pushes past the frame
       it annotates and takes the document with it. Let it wrap instead of
       truncating — the number is the point of the callout. */
    white-space: normal;
    max-width: calc(100% - 1.5rem);
  }
}

/* ---------------------------------------------------------------------------
   THE SEAM (see Seam.tsx)
   ------------------------------------------------------------------------ */
.ak-seam {
  position: fixed;
  top: 0; bottom: 0;
  left: max(0.5rem, calc((100vw - 1440px) / 2 - 44px));
  width: 60px;
  z-index: 30;
  pointer-events: none;
  mix-blend-mode: normal;
}
@media (max-width: 1100px) {
  /* Tuck to the very edge rather than dropping it — it is the brand mark. */
  .ak-seam { left: -18px; width: 60px; opacity: 0.75; }
}
@media (max-width: 640px) {
  .ak-seam { left: -26px; opacity: 0.55; }
}

/* ---------------------------------------------------------------------------
   GRAIN
   ------------------------------------------------------------------------ */
.ak-grain {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: var(--grain-opacity);
  mix-blend-mode: overlay;
  contain: strict;
}
.ak-grain__fibre, .ak-grain__film { width: 100%; height: 100%; display: block; }
@media (prefers-reduced-transparency: reduce) {
  .ak-grain { display: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   TIER 1 MOTION — compositor-thread CSS, zero JavaScript.
   ═══════════════════════════════════════════════════════════════════════════
   The site runs a deliberate two-tier motion architecture:

     Tier 1 (here)  — every reveal, progress readout and type-weight shift is a
                      CSS scroll-driven animation. It runs on the compositor,
                      costs 0KB of JS and cannot contribute to INP.
     Tier 2 (GSAP)  — only the things the CSS spec deliberately excludes:
                      pinning, scrub with programmatic control, split-text
                      choreography.

   Everything below is wrapped in @supports, so browsers without scroll-driven
   animations get the finished state immediately rather than a broken one.
   ------------------------------------------------------------------------ */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {

    /* ---------------------------------------------------------------------
       THE SIGNATURE MOVE — headline weight as a function of scroll position.
       ---------------------------------------------------------------------
       The masked line-reveal (SplitText, y:100%, stagger) became free with
       GSAP in April 2025 and is now on a large share of new agency sites.
       This is the alternative: nothing moves, nothing fades. The type simply
       gains weight and optical size as it travels up the viewport, driven by
       a view() timeline.

       Only `wght` and `opsz` are animated — deliberately. `wdth` changes the
       advance width and would reflow the line mid-scroll; weight on Fraunces
       is metrically compatible enough to hold the line breaks still.
       ------------------------------------------------------------------ */
    .ak-vf {
      animation: ak-weight linear both;
      animation-timeline: view();
      animation-range: entry 10% cover 45%;
    }

    @keyframes ak-weight {
      from { font-variation-settings: "wght" 300, "opsz" 14, "SOFT" 0, "WONK" 1; }
      to   { font-variation-settings: "wght" 700, "opsz" 144, "SOFT" 0, "WONK" 1; }
    }

    /* An accent rule that draws itself as its section scrolls through. */
    .ak-draw {
      animation: ak-draw linear both;
      animation-timeline: view();
      animation-range: entry 20% cover 40%;
      transform-origin: left center;
    }
    @keyframes ak-draw { from { transform: scaleX(0); } to { transform: scaleX(1); } }

    /* Section-level arrival. Short travel, compositor-only properties. */
    .ak-rise {
      animation: ak-rise linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 70%;
    }
    @keyframes ak-rise {
      from { opacity: 0; transform: translateY(24px); }
      to   { opacity: 1; transform: translateY(0); }
    }

    /* -------------------------------------------------------------------
       CINEMA — depth, driven by scroll.
       -------------------------------------------------------------------
       The plates arrive like set pieces: lifted, angled toward the light,
       settling flat as they take the stage. perspective() inside the
       transform keeps the vanishing point per-element — no wrapper needed.
       ------------------------------------------------------------------ */
    .ak-plate {
      animation: ak-stage linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 90%;
      transform-origin: center 85%;
    }
    @keyframes ak-stage {
      from { opacity: 0.35; transform: perspective(1100px) rotateX(7deg) translateY(34px) scale(0.97); }
      to   { opacity: 1;    transform: perspective(1100px) rotateX(0deg) translateY(0)    scale(1); }
    }

    /* Ken Burns inside the frame: the image drifts slower than the page,
       so every photograph reads as footage, not a thumbnail. Plates are
       overflow:hidden — the 8% overscale never escapes the frame. */
    .ak-plate > img, .ak-plate > video {
      scale: 1.08;
      animation: ak-drift linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
    }
    @keyframes ak-drift {
      from { translate: 0 3.5%; }
      to   { translate: 0 -3.5%; }
    }
  }
}

/* ---------------------------------------------------------------------------
   CHIPS — the movement tags on a case page; links into the Services anchors.
   ------------------------------------------------------------------------ */
.ak-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin: 1.75rem 0 0;
}
.ak-chips__label {
  font-family: var(--font-mono);
  font-size: 0.5625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-right: 0.5rem;
}
.ak-chip {
  display: inline-block;
  padding: 0.45rem 0.8rem;
  border: 1px solid var(--rule-strong);
  font-family: var(--font-mono);
  font-size: 0.5625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text);
  text-decoration: none;
  transition: border-color 250ms var(--ease-cut), color 250ms var(--ease-cut);
}
a.ak-chip:hover, a.ak-chip:focus-visible { border-color: var(--accent-line); color: var(--accent-text); }
a.ak-chip:focus-visible { outline: 2px solid var(--accent-line); outline-offset: 2px; }

/* ---------------------------------------------------------------------------
   MONOGRAM — the name, spelled out. Two display letters, each a link to its
   founder; the thread between them is the same seam that stitches the site.
   ------------------------------------------------------------------------ */
.ak-monogram {
  display: flex;
  align-items: center;
  gap: clamp(1.25rem, 4vw, 3rem);
  margin-top: 2.5rem;
}
.ak-monogram__letter {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  text-decoration: none;
  color: var(--text);
}
.ak-monogram__glyph {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(4.5rem, 12vw, 9rem);
  line-height: 0.9;
  font-variation-settings: 'wght' 500, 'opsz' 144, 'SOFT' 0, 'WONK' 1;
  transition: color 300ms var(--ease-cut);
}
.ak-monogram__letter:hover .ak-monogram__glyph,
.ak-monogram__letter:focus-visible .ak-monogram__glyph { color: var(--accent-text); }
.ak-monogram__letter:focus-visible { outline: 2px solid var(--accent-line); outline-offset: 4px; }
.ak-monogram__who {
  font-family: var(--font-mono);
  font-size: 0.5625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
  line-height: 1.7;
}
.ak-monogram__thread {
  flex: 1;
  height: 1px;
  min-width: 2rem;
  background: var(--accent-line);
  transform-origin: left center;
}
@media (max-width: 640px) {
  .ak-monogram { flex-direction: column; align-items: flex-start; gap: 1.5rem; }
  .ak-monogram__thread { width: 3rem; flex: none; }
}

/* ---------------------------------------------------------------------------
   CARD — a bounded, tappable panel (the movement cards on the front page).
   ------------------------------------------------------------------------ */
.ak-card {
  display: block;
  height: 100%;
  padding: 1.5rem 1.4rem 1.7rem;
  border: 1px solid var(--rule);
  text-decoration: none;
  color: inherit;
  transition: border-color 300ms var(--ease-cut), background-color 300ms var(--ease-cut);
}
.ak-card:hover { border-color: var(--rule-strong); background-color: var(--bg-raised); }
.ak-card:focus-visible { outline: 2px solid var(--accent-line); outline-offset: 3px; }

/* ---------------------------------------------------------------------------
   TILT — the pointer-tracking 3D card (ak.js drives the angles; this is the
   travelling sheen that sells the material). Fine pointers only, by the
   guards in ak.js; the sheen alone is harmless everywhere.
   ------------------------------------------------------------------------ */
[data-ak-tilt] { position: relative; }
[data-ak-tilt]::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(
    460px circle at var(--tilt-x, 50%) var(--tilt-y, 50%),
    oklch(0.6924 0.1812 46.21 / 0.09),
    transparent 70%
  );
  opacity: 0;
  transition: opacity 300ms var(--ease-cut);
}
[data-ak-tilt]:hover::after { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  [data-ak-tilt]::after { display: none; }
}

/* ---------------------------------------------------------------------------
   scroll-state() container queries — the header knows when it has actually
   stuck, with no scroll listener at all. Chromium-only in 2026, which is
   exactly why it is worth shipping: it costs nothing where unsupported and it
   appears in no theme on the market.
   ------------------------------------------------------------------------ */
@supports (container-type: scroll-state) {
  .ak-stick-host { container-type: scroll-state; }
  @container scroll-state(stuck: top) {
    .ak-stick-rule { background: var(--accent-line); opacity: 1; }
  }
}

/* ---------------------------------------------------------------------------
   ZERO-JS SECONDARY UI.
   @starting-style + allow-discrete give correct *exit* animations, and
   interpolate-size makes height:auto animatable — the three things that used
   to force a JS library for accordions, popovers and disclosures.
   ------------------------------------------------------------------------ */
:root { interpolate-size: allow-keywords; }

.ak-disclosure {
  transition: height var(--duration-base) var(--ease-spring-panel),
              opacity var(--duration-quick) ease,
              display var(--duration-base) allow-discrete;
  overflow: hidden;
}
.ak-disclosure[hidden] { height: 0; opacity: 0; }
@starting-style { .ak-disclosure { height: 0; opacity: 0; } }

/* ---------------------------------------------------------------------------
   Shared-element morph between the work index and a case study.
   Same-document today; the identical names carry straight over to the
   cross-document (@view-transition) build on WordPress.
   ------------------------------------------------------------------------ */
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-group(*) { animation-duration: 420ms; }
  ::view-transition-old(root),
  ::view-transition-new(root) { animation-duration: 260ms; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   TYPOGRAPHIC CRAFT
   ═══════════════════════════════════════════════════════════════════════════ */

/* text-box-trim removes the font's half-leading so a 10vw headline's cap
   height sits exactly on the rule beside it, instead of floating on invisible
   padding. Baseline as of Aug 2026; where unsupported you simply get a couple
   of pixels of extra leading, which is the correct failure mode. */
h1, h2, h3, .ak-display {
  text-box: trim-both cap alphabetic;
}

h1, h2, h3 { text-wrap: balance; }
p, li      { text-wrap: pretty; }

.font-display { font-family: var(--font-display); }

/* Fraunces defaults for the site: high optical size (display cut), SOFT off,
   WONK on — WONK is what gives the italic its singular, slightly wrong leg,
   and it is the single most identity-carrying setting available for free. */
.font-display, h1, h2 {
  font-variation-settings: "opsz" 144, "SOFT" 0, "WONK" 1;
}

/* Mono is data, never decoration. Tabular by default so figures line up in a
   column and never shuffle width while a counter runs. */
.font-mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-variation-settings: "wdth" 100;
}

/* ═══════════════════════════════════════════════════════════════════════════
   FULL-BLEED ACCENT
   ═══════════════════════════════════════════════════════════════════════════
   Almost every brand with a saturated accent spends it at 5-10% coverage on a
   grey page. Running whole sections at 100% orange with warm-ink type on top
   is the confident move, and — unlike white-on-orange, which measures 2.94:1
   and fails — ink on #f37021 measures 7.15:1 and passes AAA.
   ------------------------------------------------------------------------ */
.ak-accent-field {
  background: var(--accent-fill);
  color: var(--color-ink-950);
  --text: var(--color-ink-950);
  --text-muted: oklch(0.162 0.008 58 / 0.8);   /* ~5.0:1 on brand-500 */
  --text-faint: oklch(0.162 0.008 58 / 0.62);
  --rule: oklch(0.162 0.008 58 / 0.22);
  --rule-strong: oklch(0.162 0.008 58 / 0.42);
  --accent-text: var(--color-ink-950);
  --accent-line: var(--color-ink-950);
  --bg: var(--color-brand-500);
}

/* ═══════════════════════════════════════════════════════════════════════════
   MATERIAL PER MODE
   ═══════════════════════════════════════════════════════════════════════════
   Most dual-mode sites swap hex values. The two rooms here swap *material*:
   ATELIER gets paper fibre (a soft, low-frequency weave); RUNWAY gets film
   grain (high-frequency, higher opacity). Same content, different substrate.
   ------------------------------------------------------------------------ */
:root { --grain-frequency: 0.62; --grain-blend: multiply; }
:root[data-theme="dark"] { --grain-frequency: 0.9; --grain-blend: overlay; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not([data-theme="dark"]) {
    --grain-frequency: 0.9; --grain-blend: overlay;
  }
}
.ak-grain { mix-blend-mode: var(--grain-blend); }

.ak-grain__film  { display: none; }
:root[data-theme="dark"] .ak-grain__fibre { display: none; }
:root[data-theme="dark"] .ak-grain__film  { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not([data-theme="dark"]) .ak-grain__fibre { display: none; }
  :root:not([data-theme="light"]):not([data-theme="dark"]) .ak-grain__film  { display: block; }
}

/* Martian Mono is one of very few monos with a width axis as well as weight.
   The readout figures widen as they scroll through — the number is not just
   displayed, it is being taken. Weight rides along; width alone reads as a
   glitch. Guarded so it never runs where motion is unwelcome. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .ak-vf-num {
      animation: ak-num linear both;
      animation-timeline: view();
      animation-range: entry 15% cover 40%;
    }
    @keyframes ak-num {
      from { font-variation-settings: "wdth" 75, "wght" 300; }
      to   { font-variation-settings: "wdth" 112.5, "wght" 600; }
    }
  }
}

/* Lane diagrams draw their accent strokes as the section scrolls through.
   The paths carry pathLength="1" (set in JSX, since pathLength is an SVG
   attribute rather than a CSS property), so one keyframe drives all of them
   regardless of their real geometry. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .ak-diagram .ak-stroke {
      stroke-dasharray: 1;
      animation: ak-draw-stroke linear both;
      animation-timeline: view();
      animation-range: entry 20% cover 45%;
    }
    @keyframes ak-draw-stroke {
      from { stroke-dashoffset: 1; }
      to   { stroke-dashoffset: 0; }
    }
  }
}

/* ---------------------------------------------------------------------------
   FORM CONTROLS
   Drawn in the same hand as the rest: a ruled line rather than a rounded box.
   ------------------------------------------------------------------------ */
.ak-input {
  display: block;
  width: 100%;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--rule-strong);
  padding: 0.6rem 0;
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 1rem;
  transition: border-color var(--duration-quick) var(--ease-cut);
}
.ak-input:hover { border-color: var(--text-muted); }
.ak-input:focus-visible {
  outline: none;
  border-color: var(--accent-line);
  box-shadow: 0 1px 0 0 var(--accent-line);
}

.ak-range {
  appearance: none;
  height: 1px;
  background: var(--rule-strong);
  cursor: pointer;
}
.ak-range::-webkit-slider-thumb {
  appearance: none;
  width: 14px; height: 14px;
  background: var(--accent-fill);
  border: 0;
  /* A square handle, matching the theme switch — no stock pill controls. */
  border-radius: 0;
}
.ak-range::-moz-range-thumb {
  width: 14px; height: 14px;
  background: var(--accent-fill);
  border: 0;
  border-radius: 0;
}
.ak-range:focus-visible { outline: 2px solid var(--accent-line); outline-offset: 6px; }

/* ═══════════════════════════════════════════════════════════════════════════
   FONTS — self-hosted, subset, axis-pruned
   ═══════════════════════════════════════════════════════════════════════════
   Served from our own origin rather than Google's: it removes a third-party
   connection from the critical path, and since 2020 there is no shared cache
   across sites to lose by doing so.

   Each family was instanced to drop the axes the site never animates
   (Fraunces SOFT/WONK pinned, Bricolage wdth pinned) and subset to the Latin
   ranges actually used. 737KB of full Google-served files became 187KB, with
   every axis the CSS animates still intact:
     Fraunces      opsz 9-144,  wght 100-900   (driven by .ak-vf)
     Bricolage     opsz 12-96,  wght 200-800
     Martian Mono  wght 100-800, wdth 75-112.5 (driven by .ak-vf-num)

   size-adjust / ascent-override on the fallbacks keeps the metrics close
   enough that the swap does not shift layout — CLS from webfonts is otherwise
   the easiest own goal on a type-led site.
   ------------------------------------------------------------------------ */
@font-face {
  font-family: 'Fraunces';
  font-style: italic;
  font-weight: 100 900;
  font-display: swap;
  src: url('../fonts/fraunces-italic.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0100-017F, U+0180-024F, U+2000-206F, U+20A0-20CF, U+2122, U+2212;
}
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url('../fonts/bricolage.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0100-017F, U+0180-024F, U+2000-206F, U+20A0-20CF, U+2122, U+2212;
}
@font-face {
  font-family: 'Martian Mono';
  font-style: normal;
  font-weight: 100 800;
  font-display: swap;
  src: url('../fonts/martian-mono.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0100-017F, U+2000-206F, U+20A0-20CF, U+2122, U+2212;
}

/* Metric-matched fallbacks, so the pre-swap frame occupies the same space. */
@font-face {
  font-family: 'Fraunces Fallback';
  src: local('Times New Roman'), local('Times'), local('Noto Serif'), local('Droid Serif');
  size-adjust: 104%;
  ascent-override: 92%;
  descent-override: 24%;
}
@font-face {
  font-family: 'Bricolage Fallback';
  src: local('Arial'), local('Helvetica'), local('Roboto'), local('Helvetica Neue');
  size-adjust: 101%;
  ascent-override: 94%;
  descent-override: 24%;
}

/* Fraunces' subset defaults to wght 900 / opsz 9; state the display setting
   explicitly so nothing renders at full weight and tiny optical size. */
body { font-weight: 400; }


/* ═══════════════════════════════════════════════════════════════════════════
   WIDE GAMUT
   ═══════════════════════════════════════════════════════════════════════════
   The brand orange is chroma-limited by sRGB, not by choice: at L 0.692 and
   hue 46.21, sRGB tops out at C 0.194 while Display-P3 reaches 0.221. On a
   modern laptop or phone we are leaving roughly 20% of the colour on the table.

   So on a P3 display the accent gets hotter — and ONLY hotter. Lightness and
   hue are held to four decimals, which is what makes this safe: every contrast
   ratio in the system is a function of lightness, so nothing that was measured
   above stops being true. It is the same orange, rendered as far as the screen
   can actually take it.

   Two guards, both required. `@supports` alone is not enough: a wide-gamut-
   capable browser on an sRGB monitor will happily accept the declaration and
   then clip it, giving a flatter result than the sRGB value it replaced.
   ------------------------------------------------------------------------ */
@supports (color: oklch(0.7 0.2 46)) {
  @media (color-gamut: p3) {
    :root {
      --color-brand-400: oklch(0.755 0.1970 50);
      --color-brand-500: oklch(0.6924 0.2174 46.21);
      --color-brand-600: oklch(0.630 0.1979 42);
      --color-brand-700: oklch(0.552 0.1737 38);
    }
  }
}


/* ═══════════════════════════════════════════════════════════════════════════
   WORDPRESS BRIDGE
   ═══════════════════════════════════════════════════════════════════════════
   Zeyna puts the Barba container on <main id="primary">. These rules give that
   element the page grid and the section rhythm the prototype uses, so a
   bespoke template can be written as plain markup without a utility framework.
   ------------------------------------------------------------------------ */

.ak main#primary,
.ak-scope {
  background: var(--bg);
  color: var(--text);
}

.ak-wrap {
  width: 100%;
  max-width: 1440px;
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 3vw, 2.5rem);
}

.ak-section { padding-block: clamp(4rem, 9vw, 7rem); }
.ak-section--rule { border-top: 1px solid var(--rule); }

/* Section opener: folio, drawn rule, eyebrow, statement. */
.ak-eyebrow {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-family: var(--font-mono);
  font-size: 0.5625rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.ak-eyebrow__folio { color: var(--text-faint); font-variant-numeric: tabular-nums; }
.ak-eyebrow__rule {
  display: block;
  width: 3rem;
  height: 1px;
  background: var(--accent-line);
}

.ak-display {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(2rem, 5.5vw, 4.25rem);
  line-height: 0.94;
  letter-spacing: -0.02em;
  color: var(--text);
  max-width: 18ch;
  margin: 1.25rem 0 0;
}
.ak-display--hero {
  font-size: clamp(2.5rem, 8vw, 6rem);
  line-height: 0.9;
  letter-spacing: -0.03em;
  max-width: 15ch;
}

.ak-lead {
  max-width: 52ch;
  margin-top: 1.5rem;
  font-size: clamp(0.9375rem, 1.5vw, 1.125rem);
  line-height: 1.6;
  color: var(--text-muted);
}

/* The one full-bleed accent section per page. Ink on orange is 6.60:1; white
   on orange is 2.94:1 and fails three thresholds, so never use white here. */
.ak-accent-field { padding-block: clamp(5rem, 11vw, 8rem); }

.ak-grid {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
}
@media (min-width: 640px)  { .ak-grid--2 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px)  { .ak-grid--4 { grid-template-columns: repeat(4, 1fr); } }
.ak-grid > * { background: var(--bg); padding: clamp(1.25rem, 2.5vw, 1.75rem); }
.ak-accent-field .ak-grid > * { background: var(--color-brand-500); }

.ak-btn {
  display: inline-block;
  padding: 0.9rem 1.75rem;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  text-decoration: none;
  border: 1px solid transparent;
  transition: background-color var(--duration-quick) var(--ease-cut),
              color var(--duration-quick) var(--ease-cut),
              border-color var(--duration-quick) var(--ease-cut);
}
.ak-btn--fill { background: var(--accent-fill); color: var(--accent-on); }
.ak-btn--line { border-color: var(--rule-strong); color: var(--text); }
.ak-btn--line:hover { border-color: var(--accent-line); color: var(--accent-text); }

/* Mode switch, named rather than symbolised. */
.ak-mode {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  background: none;
  border: 0;
  cursor: pointer;
  padding: 0;
  color: inherit;
}
.ak-mode__label {
  font-family: var(--font-mono);
  font-size: 0.5625rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.ak-mode__track {
  position: relative;
  display: block;
  width: 34px;
  height: 18px;
  border: 1px solid var(--rule-strong);
}
.ak-mode__knob {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 10px;
  height: 10px;
  background: var(--accent-fill);
  transition: transform var(--dur-spring-ui) var(--ease-spring-ui);
}
:root[data-theme='dark'] .ak-mode__knob { transform: translateX(16px); }

@media (prefers-reduced-motion: reduce) {
  .ak-mode__knob { transition: none; }
}

/* ---------------------------------------------------------------------------
   MEASURE FRAME — visibility
   ---------------------------------------------------------------------------
   In the React prototype this was driven by component state. Here it is CSS,
   which is better: hover and keyboard focus cost no JavaScript at all, and the
   only thing JS does is add `.is-measured` on touch devices when the block
   scrolls into view (see ak.js). No figure is ever hover-only.

   Add `data-always` to keep a frame's annotations permanently visible — used
   for hero and statement blocks.
   ------------------------------------------------------------------------ */
.ak-measure-hud {
  position: absolute;
  inset: 0;
  z-index: 20;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--duration-base) var(--ease-cut);
}

[data-ak-measure]:hover      .ak-measure-hud,
[data-ak-measure]:focus-within .ak-measure-hud,
[data-ak-measure].is-measured  .ak-measure-hud,
[data-ak-measure][data-always] .ak-measure-hud { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .ak-measure-hud { transition: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   PLATES — the image system, as pure CSS
   ═══════════════════════════════════════════════════════════════════════════
   Halftone placeholders in the two brand colours: ink ground, orange screen.
   They are deliberately drawn rather than photographic, so a page full of
   placeholders still reads as art-directed instead of broken — and when real
   photography arrives it drops into the same box with the same treatment.

   Four screen angles so a grid of plates does not read as wallpaper. Swap any
   plate for a real image by putting an <img> inside .ak-plate — the halftone
   then becomes the loading ground behind it.
   ------------------------------------------------------------------------ */
.ak-plate {
  position: relative;
  overflow: hidden;
  background-color: var(--color-ink-950);
  background-image: radial-gradient(circle, var(--color-brand-500) 1.1px, transparent 1.1px);
  background-size: 7px 7px;
}
.ak-plate--fine   { background-size: 5px 5px; }
.ak-plate--coarse { background-size: 11px 11px; }
.ak-plate--band {
  background-image:
    radial-gradient(circle, var(--color-brand-500) 1.1px, transparent 1.1px),
    linear-gradient(115deg, transparent 0 58%, oklch(0.6924 0.1812 46.21 / 0.85) 58%);
  background-size: 7px 7px, 100% 100%;
}
.ak-plate--disc {
  background-image:
    radial-gradient(circle at 68% 42%, oklch(0.6924 0.1812 46.21 / 0.9) 0 26%, transparent 27%),
    radial-gradient(circle, var(--color-brand-500) 1.1px, transparent 1.1px);
  background-size: 100% 100%, 7px 7px;
}
.ak-plate > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.ak-plate__note {
  position: absolute;
  left: 0.75rem;
  bottom: 0.6rem;
  font-family: var(--font-mono);
  font-size: 0.5rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-brand-300);
}

/* Aspect helpers used across the templates. */
.ak-r-45   { aspect-ratio: 4 / 5; }
.ak-r-169  { aspect-ratio: 16 / 9; }
.ak-r-165  { aspect-ratio: 16 / 5; }
.ak-r-sq   { aspect-ratio: 1 / 1; }

/* ═══════════════════════════════════════════════════════════════════════════
   THE BAND — a marquee that earns its movement
   ═══════════════════════════════════════════════════════════════════════════
   Pure CSS, so it costs no main-thread time. WCAG 2.2.2 is Level A: anything
   auto-moving past five seconds needs a pause control that exists WITHOUT
   hover — hover does not exist on touch. The checkbox hack keeps even the
   control JavaScript-free.
   ------------------------------------------------------------------------ */
.ak-band {
  position: relative;
  overflow: hidden;
  border-block: 1px solid var(--rule);
  padding-block: 1.1rem;
}
.ak-band__track {
  display: flex;
  width: max-content;
  gap: 0;
  animation: ak-band-scroll 36s linear infinite;
}
.ak-band__half, .ak-band__copy { display: flex; }
.ak-band:hover .ak-band__track,
.ak-band:focus-within .ak-band__track,
.ak-band__pause:checked ~ .ak-band__track { animation-play-state: paused; }

@keyframes ak-band-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

.ak-band__item {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding-inline: 2rem;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.ak-band__key { opacity: 0.55; font-size: 0.5rem; letter-spacing: 0.18em; }

.ak-band__pause { position: absolute; opacity: 0; pointer-events: none; }
.ak-band__toggle {
  position: absolute;
  right: 0.5rem;
  top: 50%;
  translate: 0 -50%;
  z-index: 2;
  cursor: pointer;
  border: 1px solid var(--rule);
  background: var(--bg);
  color: var(--text-faint);
  padding: 0.2rem 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.5rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.ak-band__pause:focus-visible ~ .ak-band__toggle { outline: 2px solid var(--accent-line); outline-offset: 2px; }
.ak-band__toggle::after { content: 'Pause'; }
.ak-band__pause:checked ~ .ak-band__toggle::after { content: 'Play'; }

@media (prefers-reduced-motion: reduce) {
  .ak-band__track { animation: none; width: auto; }
  .ak-band__half { flex-wrap: wrap; row-gap: 0.5rem; }
  .ak-band__item { white-space: normal; max-width: 100%; }
  .ak-band__copy { display: none; }   /* the duplicate half exists only to loop */
  .ak-band__toggle { display: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   CONTACT FORM 7 — the form language
   ═══════════════════════════════════════════════════════════════════════════
   CF7 markup is what it is; these rules dress it in the house language —
   a ruled line, not a rounded box — without touching the plugin.
   ------------------------------------------------------------------------ */
.ak-form .wpcf7-form { display: grid; gap: 2.25rem; }

.ak-form .ak-field { display: block; }
.ak-form .ak-field > .ak-field__label {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.5625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 0.4rem;
}
.ak-form .ak-grid-2 {
  display: grid;
  gap: 2.25rem;
}
@media (min-width: 640px) { .ak-form .ak-grid-2 { grid-template-columns: 1fr 1fr; } }

.ak-form input[type='text'],
.ak-form input[type='email'],
.ak-form input[type='tel'],
.ak-form input[type='url'],
.ak-form select,
.ak-form textarea {
  display: block;
  width: 100%;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--rule-strong);
  border-radius: 0;
  padding: 0.6rem 0;
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 1rem;
  transition: border-color var(--duration-quick) var(--ease-cut);
}
.ak-form select { cursor: pointer; }
.ak-form select option { background: var(--bg); color: var(--text); }
.ak-form textarea { resize: vertical; min-height: 6.5rem; }
.ak-form input:hover, .ak-form select:hover, .ak-form textarea:hover { border-color: var(--text-muted); }
.ak-form input:not([type='submit']):focus-visible, .ak-form select:focus-visible, .ak-form textarea:focus-visible {
  outline: none;
  border-color: var(--accent-line);
  box-shadow: 0 1px 0 0 var(--accent-line);
}
/* The filled button needs a real ring — an underline under an orange block
   is imperceptible. */
.ak-form input[type='submit']:focus-visible {
  outline: 2px solid var(--accent-line);
  outline-offset: 3px;
}

.ak-form input[type='submit'] {
  justify-self: start;
  cursor: pointer;
  border: 1px solid transparent;
  background: var(--accent-fill);
  color: var(--accent-on);
  padding: 0.95rem 1.9rem;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  transition: transform var(--dur-spring-ui) var(--ease-spring-ui);
}
.ak-form input[type='submit']:hover  { transform: translateY(-2px); }
.ak-form input[type='submit']:active { transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  .ak-form input[type='submit'] { transition: none; }
}

/* CF7 validation states, in the house voice rather than the plugin's red. */
.ak-form .wpcf7-not-valid { border-color: var(--accent-line) !important; }
.ak-form .wpcf7-not-valid-tip {
  display: block;
  margin-top: 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.5625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-text);
}
.ak-form .wpcf7-response-output {
  margin: 0 !important;
  border: 1px solid var(--rule-strong) !important;
  padding: 1rem 1.25rem !important;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  color: var(--text);
}
.ak-form .wpcf7-form.sent .wpcf7-response-output {
  border-color: var(--accent-line) !important;
  color: var(--accent-text);
}
.ak-form .wpcf7-spinner { filter: grayscale(1); }

/* ═══════════════════════════════════════════════════════════════════════════
   WORK INDEX + CASE FURNITURE
   ------------------------------------------------------------------------ */
.ak-index { list-style: none; margin: 3rem 0 0; padding: 0; border-top: 1px solid var(--rule); }
.ak-index__row { border-bottom: 1px solid var(--rule); }
.ak-index__link {
  display: grid;
  grid-template-columns: 3.5rem 1fr auto;
  gap: 0.5rem 1.25rem;
  align-items: baseline;
  padding: 1.6rem 0;
  text-decoration: none;
  color: inherit;
}
@media (min-width: 900px) {
  .ak-index__link { grid-template-columns: 3.5rem 11rem 1fr auto 4rem; }
}
.ak-index__folio { font-family: var(--font-mono); font-size: 0.5625rem; color: var(--text-faint); font-variant-numeric: tabular-nums; }
.ak-index__client { font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text); }
.ak-index__title {
  grid-column: 1 / -1;
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.25rem, 2.6vw, 2rem);
  line-height: 1.15;
  color: var(--text);
  transition: color var(--duration-quick) var(--ease-cut);
}
@media (min-width: 900px) { .ak-index__title { grid-column: auto; } }
.ak-index__link:hover .ak-index__title,
.ak-index__link:focus-visible .ak-index__title { color: var(--accent-text); }
.ak-index__link:hover .ak-index__folio { color: var(--accent-text); }

/* Micro-motion: rows and notes step aside for the cursor on a spring. */
@media (prefers-reduced-motion: no-preference) {
  .ak-index__link { transition: transform var(--dur-spring-ui) var(--ease-spring-ui); }
  .ak-index__link:hover { transform: translateX(8px); }
  .ak-note { transition: transform var(--dur-spring-ui) var(--ease-spring-ui); }
  .ak-note:hover { transform: translateX(6px); }
}
.ak-index__tags { display: flex; gap: 0.375rem; flex-wrap: wrap; }
.ak-index__tag {
  border: 1px solid var(--rule-strong);
  padding: 0.15rem 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.5rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.ak-index__year { display: none; font-family: var(--font-mono); font-size: 0.5625rem; color: var(--text-faint); text-align: right; }
@media (min-width: 900px) { .ak-index__year { display: block; } }

/* Case chapters: numbered, with the measure in the margin. */
.ak-chapters { list-style: none; margin: 3rem 0 0; padding: 0; border-top: 1px solid var(--rule); }
.ak-chapter {
  display: grid;
  gap: 1rem;
  padding: 2.5rem 0;
  border-bottom: 1px solid var(--rule);
}
@media (min-width: 900px) { .ak-chapter { grid-template-columns: 4rem 1fr 14rem; gap: 2.5rem; } }
.ak-chapter__no { font-family: var(--font-mono); font-size: 0.5625rem; color: var(--text-faint); font-variant-numeric: tabular-nums; }
.ak-chapter__title { margin: 0; font-family: var(--font-display); font-style: italic; font-size: clamp(1.375rem, 3vw, 2.25rem); line-height: 1.1; color: var(--text); }
.ak-chapter__body { margin-top: 1rem; max-width: 56ch; font-size: 0.9375rem; line-height: 1.65; color: var(--text-muted); }
.ak-chapter__measure { align-self: start; border: 1px solid var(--rule-strong); padding: 1rem 1.1rem; }
.ak-chapter__measure b { display: block; font-family: var(--font-mono); font-weight: 700; font-size: 1.35rem; color: var(--accent-text); }
.ak-chapter__measure span { font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--text-faint); }

/* Founder spread. */
.ak-founder { display: grid; gap: 2rem; border-top: 1px solid var(--rule); padding-top: 2.5rem; }
@media (min-width: 900px) { .ak-founder { grid-template-columns: minmax(0, 22rem) 1fr; gap: 3.5rem; } }
.ak-founder__name { margin: 0.75rem 0 0; font-family: var(--font-display); font-style: italic; font-size: clamp(2rem, 5vw, 3.5rem); line-height: 0.95; color: var(--text); }
.ak-founder__role { margin-top: 0.75rem; font-family: var(--font-mono); font-size: 0.5625rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--accent-text); }
.ak-founder__bio p { max-width: 62ch; font-size: 0.9375rem; line-height: 1.65; color: var(--text-muted); }

/* Journal list. */
.ak-notes { list-style: none; margin: 3rem 0 0; padding: 0; border-top: 1px solid var(--rule); }
.ak-note { display: grid; gap: 1rem; padding: 2.25rem 0; border-bottom: 1px solid var(--rule); }
@media (min-width: 900px) { .ak-note { grid-template-columns: 4rem 1fr 9rem; gap: 2rem; } }
.ak-note__meta { display: flex; gap: 0.75rem; font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--text-faint); }
@media (min-width: 900px) { .ak-note__meta { flex-direction: column; text-align: right; } }
.ak-note__meta .cat { color: var(--accent-text); }
.ak-note__title { margin: 0; max-width: 30ch; font-family: var(--font-display); font-style: italic; font-size: clamp(1.375rem, 3.4vw, 2.5rem); line-height: 1.08; }
.ak-note__title a { color: var(--text); text-decoration: none; transition: color var(--duration-quick) var(--ease-cut); }
.ak-note__title a:hover, .ak-note__title a:focus-visible { color: var(--accent-text); }
.ak-note__excerpt { margin-top: 1rem; max-width: 62ch; font-size: 0.9375rem; line-height: 1.65; color: var(--text-muted); }

/* Long-form entry body. */
.ak-prose { max-width: 68ch; }
.ak-prose p { font-size: 1.0625rem; line-height: 1.75; color: var(--text-muted); }
.ak-prose h2, .ak-prose h3 { font-family: var(--font-display); font-style: italic; color: var(--text); margin-top: 2.5em; }
.ak-prose a { color: var(--accent-text); }

/* Bare inline links anywhere in the design system — house accent, never
   browser blue. Classed links (.ak-btn, .ak-chip, cards) style themselves. */
.ak-scope a:not([class]) {
  color: var(--accent-text);
  text-decoration: underline;
  text-decoration-color: var(--accent-line);
  text-underline-offset: 0.2em;
  transition: text-decoration-color 250ms var(--ease-cut);
}
.ak-scope a:not([class]):hover { text-decoration-color: currentColor; }
.ak-prose blockquote {
  margin: 2.5rem 0;
  padding-left: 1.5rem;
  border-left: 2px solid var(--accent-line);
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.375rem;
  color: var(--text);
}

/* Pre-footer CTA — every page closes on the same invitation. */
.ak-cta { background: var(--bg-sunk); border-top: 1px solid var(--rule); }
.ak-cta .ak-display { max-width: 16ch; }
.ak-cta__row { display: flex; flex-wrap: wrap; gap: 0.9rem; margin-top: 2.25rem; }

/* Video slot: a plate that upgrades itself when sources exist (see ak.js). */
.ak-video { position: relative; }
.ak-video video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* In a crowded mobile menu row the switch keeps its function and sheds its
   label — the aria-label still names both rooms for assistive tech. */
@media (max-width: 560px) {
  .ak-menu-mode .ak-mode__label { display: none; }
}
.ak-menu-mode { display: flex; align-items: center; }

/* WordPress's own screen-reader class, restated here so the theme never
   depends on the parent defining it — an sr-only span that renders visibly
   is worse than none. */
.screen-reader-text {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Print (and print-shaped renderers) get the finished page: a scroll reveal
   that never scrolls would otherwise print as blank rectangles. */
@media print {
  .ak-rise, .ak-vf, .ak-draw, .ak-band__track,
  .ak-plate, .ak-plate > img, .ak-plate > video { animation: none !important; scale: none; translate: none; }
  .ak-measure-hud { opacity: 1 !important; }
  .ak-seam, .ak-grain { display: none; }
  .ak-cut-half--top { clip-path: none !important; opacity: 1 !important; transform: none !important; }
  .ak-cut-half--bottom, .ak-cut-blade { display: none !important; }
}
