Digital Solutions
The whole face is the link.
Hover it: the card lifts and blooms its own accent.
Explore Digital Solutions
How the site is built
Every colour, type size, shape and motion rule this site is built from, rendered live from the real values rather than described in a document. What you see on this page is what the rest of the site is using, because it reads from the same stylesheet.
The load-bearing rule
Everywhere, without exception: icons, tags, list rails, chevrons, footer columns, hover states, chart series. When both tracks are meant together, run green into purple as a gradient rather than picking one.
Colour
Progressively lighter as elements stack toward the viewer.
Colour
The one earned green-to-purple, held solid at each end so the blend is a narrow band in the middle. Green-lift at 0 and 35%, base purple at 65 and 100%, left to right. The token is --gradient-brand, applied to text through .text-gradient-brand. Display headings only: the purple end sits at the AA large-text floor, so it never carries body-size text.
Everything working in Synrgy.
Typography
One family, Poppins. Named by role, not size.
Typography
Line length is tokenised in ch so it tracks the type it holds, generating the max-w-measure-* utilities. The rule on the right marks where each measure caps the line.
Smart systems, strong brands.
Bringing clarity to complexity by blending technical expertise with creative thinking.
The engineering and the brand are usually two suppliers, two timelines and two opinions. Here they run as one track, which is the whole point of the name.
The engineering and the brand are usually two suppliers, two timelines and two opinions. Here they run as one track, which is the whole point of the name.
No measure at all: the line runs the full width of the content column and stops only at its edge, which is how the section descriptions on this page sit so their right edge lines up with the divider rules.
Typography
--tracking-display
-0.04em · display-lg
--tracking-heading
-0.035em · display and display-sm
tracking-tight
-0.025em · Titles and figures
--tracking-numeral
0.1em · Tabular numerals in lists
--tracking-label
0.16em · Uppercase labels
Typography
h1 to h6 carry the scale as base element styles in global.css, so Markdown and un-classed prose render right without a utility class.
Punctuation takes the colour of the word before it: a mark after an accented word sits inside the span and carries the accent; after an uncoloured word it stays the main text colour.
We run both, then merge them.
Spacing and layout
Named tokens carry meaning across the site; the gap ladder is Tailwind's numeric scale, one step per role. Ties round padding up, margins and gaps down.
Named tokens
Gap ladder
Shape
Everything is angular. The cut is one 45° angle at a tokenised set of lengths by role. Reference a token, never a raw pixel.
accent
Solid accent cards
console
Consoles, large feature panels
panel
.cut-corners default (own-fill panels)
card
.panel-cut default (bordered cards)
inner
Nested panels, step cards, insets
button
Buttons
button-sm
Small buttons, badge chips
.chamfer is square-only, since its percentage cut holds 45° only when width equals height. For anything non-square, the length-based .cut-corners holds the same angle at any aspect ratio. Between them, every shape on the site is covered.
.chamfer on a square, holds 45°
.cut-corners on a rectangle, holds 45°
The one place the site rounds rather than cuts, held to Tailwind's own scale on purpose, since redefining a radius token silently changes every rounded-* on the site. Only the first two are in real use; rounding survives only at nav-control scale.
rounded-lg
Small controls, menu items, skip link
rounded-xl
Mobile nav dropdown
rounded-2xl
Available, not in use
rounded-full
The .glow blob only
Two neutral shadows, tokenised. Accent glows are drop-shadow filters carrying a track colour at the call site, so the light follows the chamfered silhouette.
Console panels' floor shadow
Mobile nav dropdown's pop
Motion
House easing is --ease-out-expo, cubic-bezier(.16, 1, .3, 1). Hover a card to feel the speed.
fast
200ms · Colour and border feedback
base
300ms · Most movement and hovers
slow
700ms · Reveals and lifts
Motion
The house moves beyond simple hovers. All rest in their final state under reduced motion.
Reveal stagger
Sibling cards land 70ms apart via a transition-delay step (the values grid, the flight-path steps).
Count-up readout
Demo figure
0+
Figures count up over 1.8s with an exponential ease-out on first view, replay after a bfcache return, and jump straight to target under reduced motion (the hero console).
Stroke draw
pathLength normalises the path so one dash covers it, and the offset draws the line along its length on reveal (the two-track merge curves).
Clip-path wipe
An already-dashed stroke reveals with a clip-path sweep instead, so two dash systems never fight (the flight-path trajectory).
Beacon float
The console mark bobs 7px on a gentle 5s loop, resting via an explicit animation: none under reduced motion (the hero and identity consoles).
Glow pulse
An accent drop-shadow breathing on a 4.5s loop, recoloured with --glow-accent. A filter, so the light follows the cut silhouette. Rests at its low value under reduced motion. Carries no information and moves no content, so it files with the beacon float and owes no pause control (the service pages' station).
Components
.field-input: the console's input, a bare hairline rectangle on the ink surface. Square corners are the site's own angular language at this scale; the border does the feedback (line at rest, line-lit on hover and focus) and the global focus ring sits on top. Labels are .telemetry, with optional fields marked in the label rather than required ones starred.
The brand indicator, replacing the round dot. Every tone.
.panel-cut
Bordered angular panel: a 1px ring with an inset tinted fill. The default card and panel.
.cut-corners
Solid accent card.
Paints its own fill, so it uses the bare corner cut rather than a ring.
.chamfer
.grid-field
.glow
Mission 001
.telemetry
.blueprint
.layout-guides
The third member of the diagram family, after the home page's merge and the Services splitter. Both of those are open figures; this one closes, because the thing it draws is a loop. It carries no explicit height, so it scales to its width with no distortion, which is what holds every corner at a true 45 degrees. A panel cuts two corners because the cut carries the mark's orientation, a circuit turns at 45 degrees at all four because it is a path rather than a plate. Direction markers are not decoration: half the nodes read right to left, so without them the loop looks like a list running backwards.
The signal is a second stroke laid over the first rather than a dash pattern on it, because the draw-on reveal already owns that path's dashes and two dash systems on one stroke fight. pathLength is set to a whole multiple of the dash period, which is what closes the loop without a jump at the seam. It carries a pause control for the same reason the marquee does, and rests with its dashes visible under reduced motion rather than disappearing.
The fourth member of the diagram family, and the only one that never arrives. A route runs in, jogs at 45 degrees, and stops at a squared cut. Past the gap the rest of it is still drawn, in the line colour, no longer connected to anything. The mark stands in the gap where the two ends no longer meet, referenced by the same bare path every other use on the site takes rather than inlined, so its geometry and gradients stay in one file and its gradient ids cannot collide if the diagram is ever drawn twice on one page.
It reuses .circuit-path for a one-shot draw that stops dead at the cut. Nothing loops, so it needs no pause control, and the reduced-motion rule that class already carries rests it drawn. No accent, because the page it belongs to names neither track. A mask fades both ends so it reads as a stretch of a longer route rather than a line with two ends.
The fifth member of the family, and the only one that belongs to a service rather than to a whole page. It is a stretch of the hub's cycle straightened out, not a crop of it: the loop runs its bottom three stages right to left, so a literal crop would read backwards on half the pages. Laid flat, every page reads the same way, what runs before this, this, and what runs after.
The route lifts to a platform and drops back after it, both ramps at 45 degrees, and the station stands on the platform. The through line is the cycle carrying on without you; the raised span is the part this page is about. A mask fades both ends so it reads as a stretch of something longer.
It draws once on reveal and then carries the hub'ssignal flow over the top, on the same 50-unit dash period, so a leaf page reads as a stretch of the same live circuit rather than a still picture of it. That means it carries a pause control exactly as the hub's loop does, sitting on the row the neighbour labels are on rather than in a strip below the band. Its path is open rather than closed, so unlike the loop there is no seam for the pattern to jump at: the whole-number path length is about holding that shared rhythm, not about hiding a wrap.
It is full bleed, sitting outside.shell so the through line runs to both viewport edges. A route that stops in mid-air is a picture of a route rather than one: an earlier pass capped it at max-w-4xl, which left it narrower than the headline it introduced and reading as a garnish. The svg is uncapped for the same reason, rendering one viewBox unit to one pixel at a 1600px viewport and scaling from there: any max-w leaves it stopping short with dead space either side on a wide display. Past about 1333px the headline has hit its clamp ceiling while the platform keeps growing, so the bracket gets more generous rather than tighter.
The station glyph hangs clear below the plate, whole, centred on its width with an 8px gap. It isthe service's own icon, so each station reads as the stop it actually is. A single shared cog stood here for a while, on the argument that the glyph meant the station rather than a service; in practice a cog reads as engineering, so it said "Development" on all six pages, which is the opposite of what a shared marker is for.
Show the whole glyph, not half of it.Two earlier passes got this wrong: the first flanked the plate with two copies, which read as wings on a sign, and the second straddled the plate's lower edge with one, showing its bottom half. The straddle worked only while the glyph was a cog. A cog is radially symmetric, so any half of it still reads as a cog; every icon in the current set has a definite top and bottom with the identifying part up top (a blueprint's roll, a toolbox's handle, a code window's chrome), so cutting the top half away removed the half that said what the thing was and left a shape nobody could name. A crop is only safe on a symmetric mark.
It is smaller than the cropped version, which is what makes clearing the plate affordable: the crop showed about half of a 130% box, this shows all of a 64% one, so it reaches only about 7px further down than the overhang already did. Sized on the drawing rather than on its box, since these icons carry artboard padding and fill roughly three quarters of it. The glyph's height and that gap are what the headline's offset is tuned against, on both routes: the flow margin belowmd and the calc above it. Measured at 375, 768, 1280, 1440 and 1800, both land on the same 21px of clearance, because the plate and glyph are fixed-pixel objects and the calc holds a fixed gap from the plate.
The platform is 62% of the band, sized against the headline it carries rather than to fit a column: at 1440px that is 893px of platform to 814px of type, so the ramps land just outside the widest line. The station is a real element rather than an svg plate, because it carries the service's animated icon, and it is opaque so it covers the stroke underneath the way the cycle's plates do. It is placed by the platform's own share of the viewBox, so the two cannot drift, and it lands exact on both axes at 768 and 1440. Its accent glow is a drop-shadow on the wrapper, since a filter on the cut element is cut away by that element's own silhouette.
The plate takes .cut-corners at--cut-console, not.chamfer, and it is the worked example oftwo tools, one angle under Shape. At 231 by 80 it is nowhere near square, so the percentage polygon resolved to a 58px leg against a 20px one, a 19 degree slash rather than the site's cut. The length-based cut holds 45 degrees at any aspect ratio, and the plate paints its own fill, which is what makes .cut-corners the right half of the pair rather than .panel-cut.
The band carries no words of its own. The two stages either side were captioned on it for a while and are gone, since they are named in full, as real links, on the cards at the foot of the page, so the drawing has no need to caption itself. What hangs under the through line is the signal's pause control alone, at the edge of the content column. Hidden belowmd along with the band, where the station drops into the flow on its own.
The seventh member of the family, and the Digital cycle's opposite number one track over. It is an artboard: a trim marked by printer's crop marks, two strokes per corner held off the corner by a gap so it stays open, a faint margin guide inside it, and six guides pulled in from off the board, each stopping dead on the margin under a short registration tick. An unbroken rectangle here would be the loop's silhouette in a different colour, which is the one thing it must not be: the difference between two hubs' drawings has to be the argument, not the decoration.
The guides arrive from all four sides deliberately, because the six are facets of one brand rather than steps in a process, and a run of six left to right would state an order the copy does not have. It draws once and stops, which is a claim and not a default: a circuit carries a signal that never stops because systems run, and a composition gets composed and is then finished. That keeps it clear of the continuous-motion rules rather than needing an exemption, so unlike the loop it owes no pause control and puts nothing in the tab order. Hidden belowmd, the same call the loop makes.
Drawn round its own words
Bold ideas.
Where a diagram is too wide to draw, the stacked cards carry its structure instead: a connector hands each card to the next down the column, and a closing note stands in for the return edge a single column has no room for. The card grid and the diagram change at the samebreakpoint, so the two are never both present and never both absent. This is what lets cards drop their numerals, since the order is drawn at every width.
Decide
A card in the column
Build
A card in the column
Measure feeds decide
A rail of what is actually inside the thing you just opened. Quieter than the two-track list rail, which is a list of subjects with icon plates, and it drops the numerals RailNav keeps, because these are contents rather than an order. The line and the ticks are pseudo-elements, so any list sits on the rail without extra markup, and every direct child gets a tick whether the list is a ul or adl. Recolour with--rail-accent.
A short list of assurances read as a console readout rather than as bullets: a labelled header strip, then one row per line separated by the panel's own hairlines. It sits beside the spec rail on a service page, so the two read as contents on one side and standards on the other, and it is deliberately the quieter of the pair. The marker is the chevron in its list-marker role, not a tick: nothing on this site draws a tick, and a check does not earn a glyph of its own.
How it gets built
Every service page under a track hub runs the same five sections in the same order: the hero with its station platform, the overview on the track's working surface, the spec (rail plus checks panel), Core Focus, and the closer with the two neighbouring stops. Four of the five are one shared component each, so a new service page is a data entry and a page file.
Core Focus is the exception, and is meant to be. It is the one section each page stages in the form of its own service, so the six read as a set without reading as one page printed six times. Development's is an assembly on a bus: a line running the width of the row, a drop into each module, and a terminal where it lands, because what that page builds is one system made of parts. A page whose Core Focus is the shared card grid,ServiceFocus.astro, has not been finished. That is the honest starting state for a new service page. All six now have their own, so that grid is imported by no page and stays anyway. Creative Services will start there.
Automation's is the same family of drawing, which is the part worth recording.When two pages need the same kind of drawing, the difference has to be the argument, not the decoration. Development's bus fades out at both edges deliberately, because that page builds one system out of parts, so its run reads as part of something longer. Automation's line begins at a plate naming what starts the work and ends at a plate naming what finishes it, because that page is about work that starts and finishes without anyone pushing it. Same geometry, opposite reading, and nothing was restyled to tell them apart.
A drawing can collect as well as distribute, but only where the copy has a terminal member. Development's line distributes into four and Automation's into five. Specialised Services' collects: three feeders rise out of the first three cards, each turning at its own height and running right to a shared trunk above the fourth, and the trunk drops into it. What licenses that is not how the four points read but what each one maps onto in the data. Three of them map onto a key feature, something we do; Clear Direction maps onto a check, something you get. Automation's five had no such member, which is exactly why the same drawing would have been a lie there.
Do not draw a sequence unless the content is one. Automation's five points are properties of the automation rather than steps in it, so the join runs above the row and taps down into all five at once. Drawing it in the gaps between the cards instead, which was the stronger picture of a hand-off, was rejected for reading left to right and implying an order that "Built for change" is not fourth in.
A drawing may carry words only if those words restate text that is present at every width. The hero's route carries none, and names its two neighbouring stops in real text at the foot of the page instead. Automation's plates do carry words, which is safe only because the spec rail above already says the same thing in text. Nothing lives only in the drawing, so nothing is lost at the widths that do not draw it.
Four is the most a row of cards takes atlg; five needs xl.Measured on the 84rem shell: four cards give each 249px of text measure, five give 181px at 1440 and 162px at 1280, and five at lgcollapse to about 110px, which is not a card. So Automation steps to three columns and then two, and its line is drawn only where the row is a single row.
A stroke sits in the middle of its box.A line drawn down the centre of a 12px-tall svg renders 6px below that box's top edge, so anything positioned off a neighbouring element has to add that half-height back or it stops short of the line it is meant to leave. Automation's drops and taps hang off the card row, which knows nothing about the svg. Check this by measurement rather than by eye: the shortfall reads as a slightly soft join, not as a break.
A diagonal costs its own run in height.A 45° line covering the distance from the first card to the fourth needs that distance again vertically, roughly 800px at 1440, and nothing here has 800px of band to spend. Anything shallower is an off angle, and this site draws 45° or it draws square, so a long join routes orthogonally onto a shared trunk instead. 45° stays where it is affordable: short elbows like the hero's ramps, and the chamfers on the nodes themselves.
A travelling signal only goes on a segment fixed in both directions. A path inside an svg that stretches with the viewport stretches its dashes with it and flattens the round caps into ovals, so a fluid horizontal run cannot carry one. Specialised Services' trunk is fixed in width and in height, so it is the one segment that can, and that is the better place anyway: the network sits still and the only thing that moves is what arrives. Note what the rule actually constrains: svg dash animation specifically. A fixed-size element moved by a transform does not stretch, so it is not bound by it, which is how Managed Services runs a marker the full fluid width of its row.
Draw a two-dimensional band as one layer, not as pieces hung off each card. Development and Automation hang their drops off the card row because each drop belongs to one card. A network that crosses columns cannot, so it goes in a single positioned layer standing on its own height directly above the row. Every x in it is a whole number of columns plus gaps, and with equal columns card n begins atn × (25% + a quarter of the gap), exact at every width with no breakpoint, because the layer and the grid are siblings of the same width. Its own height is also what lands the feeders on the card top edge with no margin to keep in step.
Above the row is a source; below it is a reference. The first three drawings all sit above the cards, where a line reads as something feeding them. Analytics puts a datum below the row instead, because consistent measurement is one reference everything gets read against rather than a supply. Graduation is what carries that: an ungraduated line reads as a conduit whichever side of the row it sits on, so ticking it along its whole length is what makes it an instrument. It runs the full width rather than stopping at the outer marks, since a reference does not begin and end at the things read against it. It also does not move, which is not an omission: a datum that drifted would not be a datum, and that is what leaves this one with no signal, no pause control, and nothing in the tab order where the drawing is not shown.
Draw the instrument, never the reading. Analytics is the one subject where a drawing can invent data, and the home page's live studio panel already sets the standard: whole numbers only, only things that actually exist, rates that undercount. A measurement drawing is bound by the same rule, so it may vary along the layout axis and never along a reading axis. Any difference in height or length between marks reads as a value, and there are no values to draw. That rules out every chart shape, bars, a trend line, a needle, a radar, and leaves the instrument itself: the datum's four registration marks are identical, and the only thing that varies across the drawing is position along the row, which encodes nothing but layout.
A drawing may pass over a row without touching it, and then its extent is what ties it there. Four of the five drawings state a relationship with the cards: Development drops into each, Automation taps into all five, Specialised Services rises out of three and drops into the fourth, and even the datum, which touches nothing, registers its marks against the card taps. Managed Services' sweep does none of that, because a monitor does not supply, collect or register, it passes over. What holds it to the row instead is that the rail spans the row exactly and stops hard at both ends: a patrol has a beat and the beat is finite. That is the deliberate opposite of the datum, which overruns the cards because a reference does not begin and end at the things read against it, and of Development's bus, which fades out at both edges because its run is part of something longer. Three lines above or below a row of four, and what each one does at its ends is the whole difference.
Nothing on the row may change as a marker passes. This is "draw the instrument, never the reading" applied to time rather than geometry. A card that brightened under the sweep would leave one card lit and three dark at every instant, and a drawing is read at an instant rather than over a full cycle, so "it is uniform over a pass" does not rescue it: what is actually on screen is a status on four named things that have none. It would also light the four in order, drawing a sequence out of four points that are properties. The softer version, a halo falling on whatever the marker is over, fails the same test for the same reason, so what glows travels with the marker and belongs to it.
Motion that never stops turns rather than restarting. A marker that jumped back to the start would leave the rail empty for an instant, and a page whose tagline is "always watched" does not get to be loose about always. A restart also imports a start and an end, and with them an order; the thing that jumps back to the beginning is a progress bar, which is the exact reading to avoid. So the sweep alternates, and it eases into the turn rather than reversing instantly, which is the more mechanical choice and not the softer one: nothing physical reverses direction without slowing down first. 14 seconds a pass, roughly 90px a second at 1440. Under about four seconds it reads as a scanner demanding attention; over about twenty you cannot tell it is moving while you are looking at it.
Travel is the frame's own width, not a number. A marker crossing a fluid row cannot be an svg dash, so it is a fixed-size element moved by a transform inside a frame inset from the right by exactly the marker's own width. Translating that frame by100% of itself then lands the marker flush on the far end at every viewport, with no calc and no breakpoint. Measured at 1024, 1280 and 1440: the marker starts on the rail's first pixel and finishes on its last, and the rail spans the card row to the pixel at all three. The frame's own box does sweep a full width past the rail, so the layer holding it clips, which also gives the glow a hard edge to meet at each end instead of letting it carry on past the beat.
Continuous motion pays for itself twice over. It needs an explicitanimation: none underprefers-reduced-motion rather than relying on the global duration collapse, which makes an infinite animation spin rather than settle, and it needs the no-JS checkbox pause control: the checkbox a direct sibling before what it controls, the control wrapped rather than bare since the focus-ring rule looks for .circuit-btn inside a sibling, and the whole band hidden below lg so nothing sits in the tab order where there is no motion to stop.
The gaps between the cards are for order, and nothing else is. Software's join runs in the grid's own gaps, on the icon line: card one hands to card two, card two hands to card three. That geometry sat unused for five stagings on purpose. It was the stronger picture of a hand-off when Automation needed a join, and it was turned down there for reading left to right and implying an order that page's five properties did not have. Software's content genuinely is ordered, so it is the first of the six to satisfy the other half ofdo not draw a sequence unless the content is one, and the geometry was held back until a page earned it. The run fills the gap exactly, which atgap-5 is 20px, so this is by some way the quietest of the six drawings: appropriate for a page about setup, which is unremarkable when it has been done right.
A member can be marked by having no mark. Software's chain stops after the third card and Ongoing Support gets nothing, because it maps onto no key feature at all and so is not a fourth step. The alternative was a visibly different connector meaning "from here on", which would have been safer to look at and would have invented a distinction the data does not make. Absence is the honest mark when the data's own answer is none. This is the same three and one split Specialised Services has, with the same licence, and the drawings still had to differ: that page collects the three into the fourth, this one leaves the fourth out of the chain entirely.
Three pages are still, and each is still for its own reason. Stillness is a claim like any other, not a default a drawing falls back to. The datum does not move because a datum that drifted would not be a datum. Software's chain draws once and stops because setup happens once, and a hand-off that kept repeating would say the work keeps being redone. Managed Services' marker never stops at all, because monitoring does not. The corollary is that every drawing has to make its case standing still anyway, since the reveal rests fully drawn under prefers-reduced-motion and with no script: motion may enact an argument but may never be the only thing carrying it.
.circuit-path's duration and delay are overridable, both defaulted. A long loop wants the slow 2s default; a 20px segment drawn at 2s crawls, and two segments drawn together say nothing about which came first. Setting--draw-duration and--draw-delay per segment is what lets a staging stagger its own reveal so the order is enacted rather than only depicted. Note also why this drawing can carry a dash reveal at all when most cannot: the runs are a fixed 1.25rem, so nothing about them stretches with the viewport, which is the same test the travelling-signal rule applies.
An earlier pass made those parts touch, as bays of one console divided only by the grid's hairlines. The argument was right and the drawing was not making it: four identical compartments read as one box ruled into quarters, and the bus they were meant to share was four stubs that each stopped at their own bay. Separate the parts and draw the thing that joins them. The modules are cards with real gaps now, and what makes them one system is the line feeding all four rather than their edges touching. The bus is drawn only where the row is a single row: at two columns and at one it would have to run behind the cards it feeds, so below lg the cards carry the section alone.
Where a staging needs dividers, prefer the grid's own gaps showing the panel ring colour through (gap-px on abg-line grid, cells painting their own fill) over a border rule per cell. That holds at one, two and four columns with no rule per breakpoint, and p-px on the panel is what keeps the grid off the ring itself.
A section is one object, not two columns with a gap. At the shell's width a rail's own reading measure leaves most of its column empty, so a rail and a checks panel set side by side read as two lists shoved to the edges with a hole between them (measured at 1440: a 784px column carrying 433px of text, then a 56px gap). The fix is a surface joining them, not more text. The spec is one console panel with both inside it, and the checks rows take flex-1 so they share whatever height the rail sets rather than leaving the bay half empty.
Cut-out artwork needs ground: a mockup with a transparent background dropped straight onto a field reads as pasted on, so it sits on a panel with a glow behind it. The panel is built as an instrument rather than a frame: a telemetry label strip naming the subject, the blueprint inside the panel where it is the literal truth (the build is the thing drawn on Digital's working surface), and a track-lit ring on the outer edge of its row. The section itself drops to.grid-field, because a working surface running under the prose as well makes the whole section one flat wash with a picture floating in it. Surface belongs to the thing being drawn; texture belongs to the section.
And the closer's two stops sit on the route, which is the hero's route turned over: a trough where the hero has a platform, running right to left, full bleed past the cards, its flat ends landing on the cards' centre line rather than the middle of the band, and no direction markers, since both cards already say the direction in words and carry their own chevrons.
The route frames the headline. The headline is pulled up into the band rather than sitting under it, so the platform and the station stand above it and the ramps come down either side. The path draws no stroke under the platform, so the open area between the ramps is exactly where the type goes. The offset has to be a function of viewport width, since the band scales with it while the gap being matched does not: it works out atcalc(120px - 9.375vw), positive on a tablet and negative from about 1280 up, which is the overlap the framing needs. At 1440 the gap under the station matches the gap above it, 80px each, and the ramps clear the widest line by 40px a side. Let that lower gap run generous rather than tight as the viewport narrows: the ramps converge as they rise, so pulling the headline higher on a narrow screen closes it against them.
Centre the trail on its words, not on its furniture. The eyebrow's leading rule is decorative, so counting it in the centring pushes the words right of the page's axis by half the rule and its gap, which reads as a misalignment against the station centred directly below. Lift the rule out of the flow and hang it off the left of the group; it is hidden belowsm, where the trail wraps and there is no single line for it to sit against.
The station's glyph costs height below the band's breakpoint. Its visible half is a little over 50px at any viewport, because it is sized off the plate and the plate's height comes from its content rather than from the scale. Above that breakpoint the half falls inside the band and costs nothing; below it there is no band, so the headline's margin has to clear the glyph outright or it runs into the type.
The backdrop is page data, not a component prop. Which canvas field a service page runs behind its hero and closer is a backdrop field on its entry inservice-pages.ts, so the shared hero stays shared and the choice sits with the page's own content. It defaults to the dot field; the Digital pages take the binary rain.
The home page's accent cards, each the whole face of a link to its track hub. One anchor and one target, so nothing needs the two-target split below. The affordance is the route-out row at the foot: a short rule, the destination named in full, and the chevron in its navigates role, deliberately not the drawer pull, which means opens-in-place. Hover is the button's language at card scale: a lift, a bloom of the card's own accent, the rule stretching and the chevron nudging onward. The glow sits on the unclipped .payload-lift wrapper between the anchor and the cut card, since a filter on the card itself would be trimmed by its own silhouette.
Digital Solutions
Hover it: the card lifts and blooms its own accent.
Explore Digital Solutions
Creative Services
The rule stretches and the chevron nudges onward.
Explore Creative Services
A card that both navigates and opens. The whole face is a link to the thing itself, which is what most people want, and the pull underneath opens it in place for a look first. That split is why the face is an anchor sitting outside thedetails, with thesummary reduced to the pull strip. Sits in a grid on items-start, so opening one card grows that card rather than stretching every card beside it.
Components
The button's quieter cousin: same chamfer at --cut-button-sm, no glow, no lift, no sheen. A filter or a choice, never an action, so it must not look like the control that starts a project. These are live, and they are the real class.
Each chip is a <label> with its radioinside it. A radio parked elsewhere on the page gets focused when its label is clicked and the browser scrolls it into view, throwing the viewport, and there is nowhere to draw a focus ring the reader can see. Tab into these and the ring lands on the chip, not on something invisible.
The reset is deliberately not a chip. The chips are the choices; this is the way back from having made one, so the same housing would file it in the set it exists to leave. It goes fully inert while it is the one selected, since there is nothing to reset to, and it has to exist at all because a radio group has no empty state.
A <details> whose summary is the whole card face. No JavaScript, keyboard reachable for free. The affordance is the drawer pull along the bottom edge, sitting on the hairline the panel opens along, so the card carries its own edge whether open or shut. A chevron alone in the top corner is not enough and is actively misleading: that position means navigates everywhere else on the site. Open it and the label changes with it. Sits in a grid onitems-start, like every other card that opens, so opening one grows that card rather than stretching every card beside it.
Less manual. More meaningful.
Identity that brings it all together.
For prose the site sets rather than builds: the legal pages, and anywhere a sentence has to carry a route out. At rest it is an underlined phrase in the hairline colour. On hover the word and its rule both take the accent, so the phrase lights rather than only the line under it. Never a substitute for a button, which is what starts something.
--link-accent defaults to green, which is already what a link hover looks like here: the nav underlines in green on every page, whatever that page is about. It is the interaction colour rather than a track claim, and it recolours per surface the way --rail-accent does.
Default, green: if you know what you were after,tell us and we will point you at it.
Recoloured on a Creative surface:see the work.
The real ServiceSpine.astro, rendered here rather than copied, so it cannot drift from what ships. On its own page it sticks after the hero and lights whichever track you are reading; here there is nothing to observe, so it shows its resting state with neither lit, which is also what a failed script leaves behind. Both entries are plain anchors either way, pointed at the services page so they reach the sections they name rather than scrolling nowhere.
Shape
A .panel-cut paints its ring as the element's own background rather than a border. That is why the ring follows the cut corners, and it is also what makes the ring paintable: give the element a background-imageand the gradient becomes the border. These three are the only treatments in use.
Track-lit, and lit on the outer edge
Digital, lit left
A horizontal gradient over the flat ring: transparent at one edge, solid in the track colour across the rest. The colour runs round three sides and fades out on the fourth.
Creative, lit right
The flat ring still shows through wherever the gradient is transparent, so the fade lands on the ordinary line colour rather than on nothing.
The pair lights on the outer edge of the row, so the two open towards the middle rather than both pointing the same way. The rule is the position, not the colour.
Corners only
.ring-corners clears the flat ring with--panel-border: transparent, then paints a corner-to-corner gradient that fades to transparent through its middle, so only the two coloured corners draw. It has to be declared after.panel-cut, whose background shorthand would otherwise clear the image.
The fade has to reach transparent, never the line colour. Fading to --color-line repaints the middle of the ring and gives an ordinary bordered panel with tinted corners, which is a different thing.
Corners only, recoloured to one track
The two ends are --ring-start and--ring-end. They default to green-lift into purple, which is what a panel takes when it speaks for the company rather than for one side of it. A panel sitting inside a track recolours the far end to that track's own accent, so a Digital page gets its corners without importing Creative's colour onto a page where nothing names Creative.
Same idea as --rail-accent and--link-accent: the stops live in one place and the call site says which accent it wants. This one is[--ring-end:var(--color-green)], the treatment the service pages' spec panel takes.
A full-bleed child covers the ring on the diagonal unless it is cut too. A panel whose content runs edge to edge (agap-px divider grid held off the ring byp-px, say) is a plain rectangle: on the straight edges that 1px leaves the ring showing, but at each 45 degree corner the child's square edge runs right up to the cut and the panel's own clip-path trims both flush, so the straight edges draw the ring and the angled ones draw the child. Give the child the same cut. It bites hardest here, where the diagonalis the treatment.
A seam is a 1px rule that says two things meet here. It takes--gradient-brand itself rather than restating the stops, and fades out at both ends through a single mask rather than two composited layers.
Join, between two stacked panels
How it works
How it feels
A negative margin of half the container gap pulls the seam back into the space the column already had, so drawing the line costs no height.
Horizon, with a punch-out
The same construction with an extra pair of stops that punch a hole where our own building stands, so the ground line stops at the tower rather than running through it. Build the end-fade and the punch-out as one gradient:mask-composite is never needed for this and is far harder to reason about later.
When two panels are a facing pair, the second is the first mirrored: rail, ticks, plates, headings and copy all run to the opposite edge, and the chevron rotates to point back at its own heading rather than off the panel. A mirror only holds where the pair does. Below the breakpoint that puts the two side by side they stack into one column, and a lone right-aligned panel has nothing to read against, so gate every mirrored class on that breakpoint and let the track colour carry the distinction below it.
The corner cut does not mirror. Every panel, plate and button on the site cuts top-left and bottom-right, so flipping the cut in one column of a pair makes it the odd one out rather than the matching half.
Icons
Animated Lottie icons, recoloured onto the palette. One icon, one meaning: green for Digital, purple for Creative, and an icon never stands for two things.
Digital
Software
Development
Managed Services
Specialised Services
Automation
Analytics
Creative
Graphic Design
Brand Identity
Website Development
Content & Social Media
Copywriting
Creative Strategy
Capability cards, one per track
Digital Solutions, the track
Creative Services, the track
Static and brand marks
The Synrgy mark
The Synrgy logo
Pattern
Items hang off a vertical gradient rail on short connector ticks, each on a chamfer icon plate. Hover recolours the connector and label to the track. The two are one template with a mirror flag, so Creative runs back towards the middle from md up and stacks left-aligned below it, where there is no facing pair for the flip to read against.
Pattern
An infinite scroller with a checkbox-driven pause: keyboard reachable and working with no JavaScript, which prefers-reduced-motion alone does not satisfy (WCAG 2.2.2).
Trusted by
Behaviour
Live on this page rather than mocked: the nav above, the contents rail alongside and the skip link are the real components, so their behaviour can be tried right here.
Site nav
Sticky, with a hairline border that fades in once the page scrolls past 16px. Links underline in green on hover, and the current page holds its underline via aria-current. The mobile menu is a details disclosure: works with no JS, keyboard accessible for free.
Skip link
The page's first tab stop. Press Tab from the top and "Skip to content" lands on a solid purple plate with on-purple text, jumping focus past the nav. The one purposeful pairing of rounded-lg and a purple fill.
Rail nav
The contents rail on this page is RailNav.astro: plain anchor links with no JS, upgraded to smooth scroll, a scrollspy that lights the current item, and a rail line that fills to where you are. Reusable via a sections prop; desktop only here; honours reduced motion.
Accessibility
Focus is a 2px purple-lift outline at 3px offset on everything interactive, and text selection carries a purple wash. Both are set once in global.css, so the whole site agrees.
Focus ring
Tab to the button to see the real ring; the plate beside it holds the same outline statically so the spec is visible without a keyboard.
Text selection
Select this sentence to see the purple highlight the whole site uses for selected text.
::selection · color-mix(in srgb, purple 40%, transparent)
Backgrounds and states
Three canvas fields, each the others' opposite number rather than a replacement. All keep the same contract to the letter: nothing under reduced motion, gated before init; parked off screen and in hidden tabs; gone below 40rem; two registers, full andsparse. What differs is the subject. The dot field is the company's and drifts purple into green; the rain is green only, because it belongs to pages that are entirely Digital, and it runs across the Digital Solutions hub and its service pages; the connection field is the contact page's, green on the left half and purple on the right, the sides its two routes arrive from, with cross-track links in dim so no line passes through the muddy midpoint; and the compose field is Creative's, purple only for the rain's reason, drawing the site's own cut plates scattered out of true rather than particles or glyphs.
Every field answers the pointer, and each answers in its own subject's terms: the connection field's nodes shy away and ease back, the dot field takes a pressed dent with a soft rim, the rain shelters a domed canopy over the cursor, dry beneath, splattering droplets off the dome, and the compose field's scattered plates square up and land on a baseline. One contract covers all four: the pointer is read off the window with the canvas stayingpointer-events-none, the response chases a smoothed pointer with an eased strength so arriving and leaving are movements rather than snaps, and none of it exists under reduced motion. A new field earns its own honest response, never a copy, which the compose field is the first to be held to: the umbrella belongs to rain, the dent belongs to water, and alignment belongs to a layout. Move your mouse over the tiles below to feel each one.
Two things the rain has to get right. Columns are seededacross the whole fall rather than above it, or the hero sits empty for seconds while the slowest ones descend. Andctx.font cannot resolve a custom property, so the family is read off the stylesheet first: an invalid font string is dropped silently, leaving the canvas default. Glyphs are hashed per cell and flip on a staggered per-cell clock, so nothing flickers per frame and the grid never turns over all at once.
DotWave field
BinaryRain field
NodeField field
ComposeField field
.rise reveal
Everything above is read from the same stylesheet the rest of the site runs on, so this page cannot fall out of step with what it documents.