/* The site's one handwriting face. Lachlan, 4 Nov: Reenie Beanie was "difficult to
   read", he picked Kalam from a side-by-side. Every page names "Apex Hand", so changing
   the face is this one block. The pages' font sizes were set for Reenie's tiny letters,
   so size-adjust brings Kalam's bigger ones back to fit the same lines and boxes. */
@font-face { font-family: "Apex Hand"; src: url("../fonts/kalam-latin-400-normal.woff2") format("woff2"); font-display: swap; font-style: normal; font-weight: 400; size-adjust: 68%; }

/* ══════════════════════════════════════════════════════════════════════════
   Apex Ascents — design tokens. The single source of truth, and this time
   it is actually loaded.

   ★ WHY THIS FILE WAS REWRITTEN, 2026-08-31.
   The previous tokens.css described the DARK system: #050a18 grounds, Avenir
   Next headings, Inter body, 28px radii, 800 weights. It also said "single
   source of truth" at the top. Both were false. Nothing enqueued it, and the
   site had been on the light system for two weeks. It has been archived whole
   to _archive/tokens-dark-fossil-2026-08-31/ rather than deleted.

   Its deadness is the root cause of nearly every anomaly in the site audit:
   with no live token layer, fourteen stylesheets each declared their own
   Instrument Sans stack and their own palette, 217 custom properties in total.
   The chrome's Avenir Next came directly from the fossil above.

   ★ THE VALUES BELOW ARE NOT NEW. They are what home.css, svc.css, csd.css
   and wfa.css already ship, which is why they can be adopted with no visual
   change at all: those four sheets are byte-identical in every shared role.
   Where a page keeps a prefixed name (--hm-ink, --svc-brand), that name now
   aliases a token here instead of repeating a literal. A page can still
   override one role locally; it just cannot drift by accident.

   Loaded globally by functions.php ahead of main.css, so every sheet and
   every template can reference these.
   ══════════════════════════════════════════════════════════════════════════ */

:root {

    /* ── INK ────────────────────────────────────────────────────────────────
       Three ranks, and page text uses no others. `ink` is every heading and
       anything that must be read first; `body` is sentences; `soft` is the
       things a reader may skip. */
    --a-ink:            #0a1730;
    --a-body:           #33415e;
    --a-soft:           #4d5b74;

    /* ── BRAND ──────────────────────────────────────────────────────────────
       One blue. `deep` is its pressed and hovered state, never a second
       brand colour. */
    --a-brand:          #22458a;
    --a-brand-deep:     #16305f;

    /* ── VERDICT HUES ───────────────────────────────────────────────────────
       These carry meaning and are never decoration. Green says a thing exists
       and runs today. Amber says it is built for you, or held. Red says this
       is the cost of the old way, or the thing being argued against. */
    --a-go:             #166a47;
    --a-hold:           #7a5600;
    --a-no:             #a03123;

    /* ── GROUNDS ────────────────────────────────────────────────────────────
       White is the page. Paper is the ONLY second ground on the site: it is
       what a panel sits on when it must separate from the sheet without
       becoming a different world. Card is the fill of an object laid on
       either of them. */
    --a-page:           #fff;
    --a-paper:          #f2f6fb;
    --a-card:           #fff;

    /* ── LINES ──────────────────────────────────────────────────────────────
       All three are the ink at low alpha, never a grey. A grey hairline on a
       blue-black page reads as dirt. */
    --a-line:           rgba(13, 35, 80, .14);   /* a real division           */
    --a-hair:           rgba(13, 35, 80, .09);   /* a hint of one             */
    --a-card-line:      rgba(13, 35, 80, .14);   /* the edge of an object     */

    /* ★ .14, not .1. The service pages drew a card edge at .09 to .10 and the
       hub and four app pages drew it at .14, so the same object had two
       different edges depending on which page you were on. DESIGN.md names
       .14 and it is the majority, and against a soft shadow the lighter edge
       simply disappeared. */

    /* ── ELEVATION ──────────────────────────────────────────────────────────
       Every shadow carries an offset and a soft blur; none is a zero-offset
       halo. Three steps only: resting, raised, and the plate that is meant to
       float clear of the sheet. */
    --a-lift:       0 1px 2px rgba(10, 23, 48, .04), 0 12px 28px -14px rgba(10, 23, 48, .18);
    --a-lift-2:     0 2px 4px rgba(10, 23, 48, .05), 0 26px 54px -22px rgba(10, 23, 48, .26);
    --a-plate-lift: 0 2px 6px rgba(10, 23, 48, .05), 0 40px 80px -34px rgba(10, 23, 48, .38);

    /* What a CARD gets, named for what it is rather than how high it sits, so
       a page sheet does not have to know which lift is the card one.
       ★ The hub and the four app pages ran a second, unrelated elevation:
       0 18px 40px rgba(13,35,80,.07). Diffuse, no contact edge, so the card
       hazed rather than sat. Six elevations existed across the site including
       one card with no shadow at all and one with an inverted white
       highlight. These two are all there is now. */
    --a-card-shadow:    var(--a-lift);
    --a-card-shadow-2:  var(--a-lift-2);

    /* ── GEOMETRY ───────────────────────────────────────────────────────────
       ★ ONE SHELL. 1200px with 120px gutters at 1440. Home, the services
       index and the three service pages already sit on it exactly; every
       other page is being brought onto it. `--a-shell-narrow` is for prose
       that needs a reading measure, `--a-shell-wide` for a deliberate
       edge-to-edge device. */
    --a-shell:          min(1200px, 92vw);
    --a-shell-narrow:   min(880px, 92vw);
    --a-shell-wide:     min(1400px, 95vw);
    /* ★ TWO RADII. Both were declared here months ago and neither was ever
       used, which is how eleven of them ended up on the site (6, 10, 14, 15,
       16, 18, 20, 22, 24, 26, 30). They sorted the pages into a
       small-cornered half and a large-cornered half by build date, and corner
       radius is one of the most legible style cues there is.

       A drawn artefact is exempt: it is a picture, and it sets its own
       corners the way it sets its own type. */
    --a-r:              20px;   /* an object: card, panel, window */
    --a-r-sm:           12px;   /* a control: button, input, chip */

    /* ── TYPE ───────────────────────────────────────────────────────────────
       ★ FIVE RANKS, and page text may use no others:
         head 46 · sub 22 · spoken 19 · body 16 · mark 13.
       Anything between them makes the reader work out the hierarchy instead
       of reading it. Sizes INSIDE a drawn artefact are exempt: a window is
       its own object and is not compared to the page around it.

       --a-t-h1 is the interior-page headline. The homepage does not use it:
       its h1 is a bespoke three-rank climb and stays that way. */
    --a-sans: "Instrument Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
    --a-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

    --a-t-h1:       clamp(2.4rem, 4.4vw, 3.9rem);   /* 62px at 1440          */
    --a-t-head:     clamp(1.85rem, 3.3vw, 2.85rem); /* 46px: every section   */
    --a-t-sub:      1.38rem;                        /* 22px: every h3        */
    --a-t-spoken:   1.19rem;                        /* 19px: used sparingly  */
    --a-t-body:     1rem;                           /* 16px: every sentence  */
    --a-t-mark:     .82rem;                         /* 13px: never a sentence*/
    --a-t-btn:      .96rem;                         /* 15.36px: every control*/
    /* The one licensed exception to the head rank: a page's closing line, the
       last thing before the footer, gets a step up. Five pages each invented
       their own step (49, 52, 54, 56); this is the homepage's, which is the
       most recently approved. */
    --a-t-close:    clamp(2.1rem, 3.8vw, 3.25rem);  /* 52px */

    /* The paragraph directly under the h1. Ten different sizes were in use
       across thirteen pages, from 14.4px on Workflow Automation to 20.4px on
       the homepage, on the second most prominent line of every page. */
    --a-t-lede:     1.19rem;                        /* 19px */

    /* The question in a FAQ row. Not a new rank: it is the spoken rank, named
       for its job because eleven pages each sized this one component
       differently. 16.48, 16.8, 16.96, 17, 17.28, 19 and 22.08px, at weight
       600 on seven pages and 700 on four, for the same `<summary>`. */
    --a-t-ask:      var(--a-t-spoken);

    /* The tracked uppercase label inside a drawn artefact: a window title bar,
       a status strip, an axis end, a field label. Tracked uppercase is banned
       in page copy - there are no eyebrows on this site - but inside a drawing
       it is the chrome of the software being drawn, so it stays.

       It was nine sizes (10.88 to 13.12), ten letter-spacings (.04 to .18em)
       and four weights (500, 600, 700, 900) across eleven widgets on seven
       pages. Nobody can see 11.84 against 12; everybody can see that the
       drawings do not look like one product. */
    --a-t-micro:     .78rem;                        /* 12.48px */
    --a-track-micro: .09em;

    /* ── THE OPENING ────────────────────────────────────────────────────────
       One distance from the fixed nav to the first line, on every page.

       Pages used to size the hero as a fraction of the viewport and then
       centre the copy inside it. That makes the opening depend on how much
       copy the page happens to carry, so the h1 landed anywhere from 92px
       (blog, About, Contact) to 332px (the apps hub) below the nav, and the
       pages with the least copy got the most empty screen. The gap is fixed
       now and the hero grows to fit what is in it. */
    --a-hero-pt:    clamp(112px, 15vh, 178px);
    --a-hero-pb:    clamp(72px, 9vh, 116px);

    /* ── WHERE A JUMP LINK LANDS ────────────────────────────────────────────
       The fixed header sits at top 14px and stands 60px tall, so it covers
       the page down to y=74. This is that, plus the same 14px of air it has
       above it. ONE number, and apex-lenis-boot.js reads it from here rather
       than carrying its own copy, because the two had drifted apart: CSS said
       scroll-margin-top of 96 to 128px on three pages, 96 on the hub and 80
       in main.css, while the scripts scrolled to an offset of 76 on eight
       pages, 90 on the hub and 10 on the homepage. Nine numbers for one
       header, so the same click landed in a different place on every page. */
    --a-anchor:     88px;

    /* ── HOW CONTENT ARRIVES ────────────────────────────────────────────────
       The owner set this shape on 2026-08-25: content travels 46px out of a
       7px blur. Four pages shipped it. The other ten invented their own and
       every one of them was quieter: 24px with no blur at 0.7s on AI
       Consulting and the four app pages, 0.8s on About, 18px at 0.65s on the
       hub, and nothing at all on Contact and Blog, which arrived already
       finished. So the same brand rose slowly out of a haze on four pages and
       snapped flatly into place on the rest. One motion now, from here. */
    --a-ease:       cubic-bezier(.22, 1, .36, 1);
    --a-rev-y:      46px;
    --a-rev-blur:   7px;
    --a-rev-fade:   .95s;
    --a-rev-move:   1.05s;
    --a-rev-step:   110ms;

    /* ── THE KEYBOARD RING ──────────────────────────────────────────────────
       Nine pages drew a brand ring and five did not, so Services, Workflow
       Automation, Contact and Blog fell back to Chrome's own 1px #005FCC and
       Custom Software showed BOTH within one page depending on which control
       you tabbed to. A keyboard visitor should not be able to tell which page
       they are on from the ring. */
    --a-focus:      2px solid var(--a-brand);
    --a-focus-off:  3px;
}

/* Zero specificity: the floor for every focusable thing on the site. Any page
   that wants a tighter radius on its own control still wins. */
:where(a, button, summary, input, select, textarea, [tabindex]):focus-visible {
    outline: var(--a-focus);
    outline-offset: var(--a-focus-off);
}

/* Zero specificity, so any page sheet still wins, but no anchor target on the
   site is left to land under the header by accident. */
:where(main [id]) { scroll-margin-top: var(--a-anchor); }

/* The UA sheet gives <b> and <strong> `font-weight: bolder`, which is RELATIVE:
   inside a 400 paragraph it resolves to 700, and inside a 600 label it resolves
   to 900. That is how "20/20" inside the Business Apps check header came out at
   900 - a weight this site uses nowhere - without a single stylesheet asking
   for it. The ladder is 400 and 600, so name it. Zero specificity: every
   component rule that sets its own weight still wins. */
:where(b, strong) { font-weight: 600; }

:root {

    /* ── RHYTHM ─────────────────────────────────────────────────────────────
       A RANGE, not a value. Using one number for every gap was what made the
       homepage read as a stack of unrelated blocks: the floor binds sections
       that belong together, the ceiling marks a change of subject. */
    --a-gap-group:  8rem;
    --a-gap-move:   clamp(11rem, 22vh, 14rem);

    /* ★ The rhythm was the loudest reason the pages read as different sites.
       Every page had invented its own single number: 160px on the service
       pages, 120 on AI Consulting and three of the apps, 100 on the hub, 80
       on Website Assistant, and a padding ladder of 86/101/115/144 on About.
       Six rhythms on one site, four of them under the owner's 8rem floor.
       They all take --a-gap-move now, and --a-gap-group stays available for a
       page that genuinely binds two sections, which today only the homepage
       does. The small-screen step lives here too: the homepage stepped down
       at 560px and the service pages at 640, which is a seventh rhythm on a
       phone. */

    /* ── BUTTONS ────────────────────────────────────────────────────────────
       One control, two weights. These are svc-btn's measurements, which is
       what the homepage and the three service pages already ship, and which
       the owner has signed off. Every other page had invented its own: six
       radii from 0 to 999px, four heights, three weights and two different
       primaries. A visitor crossing three pages met three different buttons.

       The solid is brand blue, not the ink navy. Navy on a light page reads as
       a heading that happens to be clickable; the blue reads as an action. */
    --a-btn-pad:    .92rem 1.5rem;
    --a-btn-r:      12px;
    --a-btn-font:   600 var(--a-t-btn)/1 var(--a-sans);
    --a-btn-glow:   0 2px 6px rgba(34, 69, 138, .26),
                    0 18px 34px -18px rgba(34, 69, 138, .7);

    /* ── MOTION ─────────────────────────────────────────────────────────────
       One curve, declared once, up in THE REVEAL. Exponential ease-out. */
    --a-dur-fast:   .3s;
    --a-dur:        .86s;
    --a-dur-slow:   1.06s;
}

/* ─────────────────────────────────────────────────────────────────────────
   THE SCROLL CUE

   Six pages carried a little animated mouse under the hero and seven did
   not, which by itself made them read as different sites. It also stopped
   being true on 2026-08-31: the heroes used to fill the viewport, so the cue
   said "there is more below". They size to their content now, so the next
   section is already on screen and the cue points at nothing while sitting
   in a band of white of its own making.

   The five `<a class="*-hero__cue">` elements were removed from the markup
   rather than hidden here, because tokens.css loads FIRST and a rule in it
   cannot outrank `body.apex-aic .aic-hero__cue` in a page sheet. The dead
   `__cue` rules are still in those five sheets and are harmless; a page that
   wants the cue back only needs its one line of markup.
   ───────────────────────────────────────────────────────────────────────── */

/* ─────────────────────────────────────────────────────────────────────────
   THE RHYTHM ON A PHONE

   One breakpoint for the whole site. The homepage stepped its section gap
   down at 560px and the service pages at 640, so between those two widths
   they were on different rhythms; every other page never stepped down at
   all and carried a 14rem gap onto a 390px screen.
   ───────────────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
    :root {
        --a-gap-group: 5.5rem;
        --a-gap-move:  clamp(5.5rem, 11vh, 8rem);
    }
}

/* ─────────────────────────────────────────────────────────────────────────
   TWO LIST MARKERS, AND ONLY TWO

   The site was running six: a 9x9 drawn square (the closes), a 9x1 dash, an
   8x2 dash, a 6px dot, an inline SVG tick, and a round green tick badge. A
   marker carries meaning, so there are two.

     BULLET  a drawn square in brand ink. Any unordered prose list.
     TICK    a masked check in the go green. Only for what is INCLUDED:
             what you are promised, what you get, what is in the price.

   There is one more, used once: the homepage's "who this is wrong for" list
   takes the tick's glyph as a cross, at the tick's size, in the hold amber.
   It is the tick negated, not a fourth marker.

   Numbers stay for an ordered process, and an artefact's own interior marks
   (a document outline, a checklist inside a drawing) are not list markers
   and are left alone. The tick's glyph lives here because it is a mask, so a
   page only has to name the size and the colour.
   ───────────────────────────────────────────────────────────────────────── */
:root {
    --a-mark:       9px;
    --a-mark-tick:  13px;
    --a-tick:       url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M1.6 6.4 4.4 9.2 10.4 3' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
