Skip to content

Say what we do in words people already use - #25

Open
drmowinckels wants to merge 22 commits into
mainfrom
service-copy
Open

drmowinckels wants to merge 22 commits into
mainfrom
service-copy

Conversation

@drmowinckels

@drmowinckels drmowinckels commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Why

People arrive unsure whether we can help them, and the copy is a large part of
why. The site described itself in terms a reader only understands if they
already know what we do — "data engineering", "data science team", "FAIR
principles", "containerization", "integrated solutions", "standardized data
output", "registry data handling 55%".

This rewrites the language across the whole site so a researcher can recognise
their own situation without knowing what any of it is called.

What changed

Services — now problem-led. Each of the seven leads with the problem the
reader arrived with, lists the situations that produce it, and says what you
get. The category name stays as a small secondary label, so someone who does
know the term can still find it.

Before   Data Engineering
         Collecting and managing data and keeping track of its lineage
         is a critical aspect of scientific research. We can provide
         guidance and advice on obtaining, cleaning and securely
         managing your data...

After    Your data isn't ready to analyse.
         - Sixty spreadsheets with inconsistent column names.
         - A Nettskjema export nobody has opened yet.
         - Scanner output that has to be organised before anything runs.
         What you get: one documented dataset you can actually use, and
         the script that produces it, so it reruns when more data arrives.

The named systems do a lot of the work. Someone who has never heard "data
engineering" knows exactly what "I have a Nettskjema and can't get the data
out" means. Every name used (Nettskjema, TSD, Educloud, Saga, Quarto) already
appeared elsewhere on the site.

Hero and contact. The hero now names the concrete things we do instead of
"capture, process, manage and analyse". Contact says explicitly that you do not
need to know the technical name for your problem, because that is the real
barrier.

Feature section. "Integrated Solutions / Standardized Data Output /
Customization on Demand" is replaced by what working with us is actually like:
we use systems UiO already pays for, you own what we build, we can teach rather
than do, and you can start with a single hour.

Skills. The percentage bars are gone. "Registry data handling 55%" is not
something a visitor can act on, and the numbers were not sourced from anything.
They are replaced by three plain lists — languages and tools, UiO and national
systems, kinds of data — so someone with MRI data on TSD recognises themselves.

Pricing. Explains that the rate depends on how close you are to the
department and that computing time is applied for and paid for separately. The
bullets describe what you get rather than listing line items.

CTA, portfolio, team, testimonials. Same rule throughout: ordinary words,
concrete claims, and an explicit invitation to ask even if your problem is not
on the list.

Also fixed

  • The English service list had Workshops but no Data capture; the Norwegian had
    Datafangst but no separate processing entry. The two languages advertised
    different services. Both now carry the same seven.
  • A duplicated skipToContent block in both i18n files.
  • Dead .progress-bar-track / .progress-bar-fill CSS, now that the bars are
    gone.

Notes

Test plan

CI covers prettier, the content accessibility check, a strict Hugo build and the
CSS bundle freshness. What it cannot check:

  • Are these seven problems the ones people actually arrive with? This is my
    best reconstruction from the services, portfolio and testimonials — you
    have the real record in the booking notes and inbox.
  • The practical: lines describe how you work, and I inferred them from the
    site and testimonials (e.g. working alongside a student comes from the
    DRCMR quote about "daily sparring and guidance sessions"). Check them.
  • Norwegian throughout is mine and wants a native read. "Finansiøren krever
    en datahåndteringsplan" in particular — is that how a Norwegian funder
    context would phrase it?
  • The skills lists are what I could infer from the team pages and portfolio.
    Add anything missing, remove anything we don't really do.
  • Pricing now states "the closer to the Department of Psychology, the
    cheaper" as plain English for the multiplier table. Confirm that is a fair
    description of the policy.

Since the first review round

Barbara's note was that the page held too much information and felt scattered,
and suggested structuring it around the four pillars in CAPRO_services.docx.

Those four — GOAT, MRI, statistical analysis, Bevex — are not a service
taxonomy. Two are named products, one is a research domain, and one is already
the "Processing and analysis" service under another name. Making them the spine
would leave work that fits none of the four homeless.

So they go in as a second layer instead. The seven problems stay the spine
and answer can you help with my problem. A short block under them, on both the
landing page and /services/, names the things a visitor already has a word
for, and answers do you do the specific thing I came for — which is how the
would-be clients in Barbara's account actually arrive.

What we run and support — GOAT, Nettskjema, MRI, behavioural experiments.
Nettskjema is in there although the document never mentions it, because it is
the one name clients were reported to ask about most.

Two of the document's claims are deliberately not made:

  • No MR scanning. The document describes collection through LCBC's
    MRI-trained staff at Oslo University Hospital. That is their capacity, not a
    CAPRO service. The card starts from scans that already exist, whoever
    collected them.
  • Bevex is not advertised. It is in testing, beta is expected spring 2027,
    and the site should not sell what it cannot deliver. The card describes what
    we can do today — build browser-based experiments in JavaScript with
    tachisto, exportable to Cognition.run, Pavlovia or JATOS — and mentions the
    UiO platform as in development, with no date.

Open source page

It said "Open source we have built" and listed four things. The organisation has
twelve worth showing. Someone judging whether we work in the open was judging us
on a third of the evidence.

Added: tachisto, uiothemes, tsdrtools, neuromat, ebrains.kg, nva,
the Nettskjema data inspector, and the R project-management workshop materials.
Two new categories, Web apps and Teaching.

The reason the rest were missing is that the card template required a local
image resource, and almost none of them ship a logo. The image panel is gone:
each card is now the categories, the linked name and a sentence. Four orphaned
logo files are deleted with it.

Accessibility and performance

Four WCAG failures fixed, 8.5 MB of unused bytes dropped, the logo hinted as the
LCP element, card images no longer upscaled, a real social card instead of a bare
logo, and card links that name their destination.

Bugs found while building this

  • .svc__deliver p never matched: markdownify returns text without its
    wrapping <p>, so every "What you get" box rendered unstyled. The CSS was
    added earlier in this same PR.
  • The portfolio blurb fallback reads .Plain, which carries the renderer's
    entities, so "Norway's" rendered as the literal &rsquo;. None of the
    original four entries had an apostrophe, so it had never surfaced.

Still to do before merge

  • Norwegian needs a pass. The plan is DeepL from the English, which is
    the source of truth. content/offerings/_index.no.md is two revisions
    behind its English twin — its experiments card has neither the platform
    list nor the tachisto mention.
  • tachisto links point at the old URL. capro.dev/tachisto/ and
    github.com/capro-uio/tachisto are both 404; capro.dev/jspsych-studio/
    is the only URL that resolves, so that is what the two link: lines use.
    Note that renaming the repo redirects the repo URL but not the GitHub
    Pages project path — capro.dev/jspsych-studio/ will 404 once the repo
    moves, so those links have to change in the same sitting as the rename.
  • GOAT wording. "Built through UiO's HUB-node initiative" is the one
    phrase in the block an outside reader will not parse. Keep only if it
    earns its place on credibility.

CI fix carried here

themes/capro-tw/layouts/partials/nav.html walked site.Languages, deprecated
in Hugo 0.156. Under --panicOnWarning that is a hard error, and the strict
build in CI failed on it on the first push of this branch. Both language
switchers now walk hugo.Sites, which carries the same weight ordering.

It is unrelated to the copy work, but it blocked this PR, so it is fixed here
rather than in a follow-up.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

✅ Preview deployed at https://25--capro-uio.netlify.app
Please check it looks ok before merging.

@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

✅ Accessibility: no issues

axe-core over 19 routes × 2 viewports (one page per layout), plus 69 manual checks.

All 69 manual checks passed.

Automated tooling catches roughly a third of accessibility problems. A clean run is a floor, not a ceiling.

drmowinckels and others added 3 commits October 18, 2026 12:31
The old entries described a category. A researcher reading one could not
tell whether their problem was in it, whether we would do the work or
advise on it, or what they would end up holding.

Each of the seven now leads with the problem the reader arrived with,
lists the situations that produce it, and says what you get. The category
name stays as a secondary label, so someone who does know the term can
still find it.

Named systems do a lot of the work: someone who has never heard "data
engineering" knows what "I have a Nettskjema and can't get the data out"
means. Every name used already appears elsewhere on the site.

Also fixes a pre-existing inconsistency where the English list had
Workshops but no Data capture, and the Norwegian had Datafangst but no
separate processing entry. The two languages advertised different
services; both now carry the same seven.

Drops the duplicated skipToContent block in both i18n files.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
"Data flow and processing 90%, Registry data handling 55%" told a reader
nothing they could act on, and the numbers were not sourced from
anything. A visitor trying to work out whether we can help them cannot
use a percentage.

It is now three plain lists — the languages and tools we use, the UiO and
national systems we work inside, and the kinds of data we handle. Someone
with MRI data on TSD can now recognise themselves on the page, which is
the whole point.

Drops the now-unused progress bar CSS.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
People kept arriving unsure whether we could help them, and the copy was
a large part of why. The site described itself in terms a reader only
understands if they already know what we do: "data engineering", "data
science team", "FAIR principles", "containerization", "integrated
solutions", "standardized data output".

Hero and contact: the hero now names the concrete things we do — tidy up
messy data, set up collection, make analyses run twice, get jobs onto
university servers, teach groups to do it themselves — rather than
"capture, process, manage and analyse". Contact says you do not need to
know the technical name for your problem, because that is the actual
barrier.

Feature section: "Integrated Solutions / Standardized Data Output /
Customization on Demand" said nothing a reader could act on. It now
answers what working with us is like — we use systems UiO already pays
for, you own what we build, we can teach instead of doing, and you can
start with a single hour.

Pricing: explains that the rate depends on how close you are to the
department, and that computing time is applied for separately. The
bullets describe what you get rather than listing line items.

CTA, portfolio, team and testimonials follow the same rule: ordinary
words, concrete claims, and an explicit invitation to ask even if your
problem is not on the list.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@drmowinckels drmowinckels changed the title Rewrite the services in problem language Say what we do in words people already use Oct 19, 2026
drmowinckels and others added 19 commits October 19, 2026 12:12
Five lines of body copy over a photographic background is hard to read,
and the list of services below it already carries the detail.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
"What you get" was a hard-coded h4 under a problem heading that is an h2
on /services/, so every item skipped h3. axe flagged 28 instances across
the two language versions.

The label now tracks the item level the same way the problem heading
does, so the pair stays one step apart whichever level the section sits
at.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The copy claimed "anyone at UiO can ask", which told a public agency or a
company that the site was not for them — while the pricing table has had
non-commercial and commercial rates all along. The two contradicted each
other, and the copy was the wrong one.

UiO stays the primary audience, since that is where most of the work
comes from, but the hero, services intro, contact, CTA and pricing now
all say plainly that public agencies and private companies can hire us.

"We use what UiO already pays for" also assumed a UiO reader; it now
covers working inside whatever systems you already have.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The hero ended on who we do and don't work for, and the contact and CTA
both ended on who gets charged. Neither is what someone reads those for,
and the "free for some, billed for others" construction read as a
disclaimer rather than an invitation.

Getting in touch is free for everyone, so saying otherwise next to the
contact form was also just wrong. The rates live on the pricing page,
which is where someone goes looking for them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Seven identically shaped blocks down the left half of the page, with the
right 40% empty, gave a reader nothing to navigate by and no sense of
where one item ended and the next began.

Each item is now a two-column grid: the problem, its category and a
numeral on the left, the evidence and the payoff on the right. The
numeral is decorative and aria-hidden — the items are not a sequence and
nothing refers to them by number; it is there to give the eye something
to count. "What you get" picks up an accent rule, since that is what a
reader is scanning for. Collapses to one column below 900px.

Also fixes the h1 promotion under `hugo server`. section-title.html
marks the page's h1 as used via Scratch, which outlives a render, so
after the first rebuild the flag stayed set and no page emitted an h1
again. Production builds render each page once and were unaffected, so
this only ever showed up locally. baseof.html now clears it where each
render starts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
"Real projects, and what we actually did on each one. If something here
looks like your situation, say so when you get in touch." read as client
case studies. Everything listed is open source or openly released
science that anyone can pick up without hiring us, which is a stronger
thing to say and happens to be true.

The nav label "Our work" carried the same wrong implication; it is now
"Open source".

ggseg becomes ggsegverse, covering the whole family of packages rather
than the one entry point. /portfolio/ggseg/ redirects to the new URL.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
--color-primary (#c04545) is a background fill. Used as a foreground it
lands at 2.68:1 on the grey sections — under the 3:1 WCAG asks for
meaningful non-text content, and nowhere near the 4.5:1 for text. The
palette already carries --color-primary-text (#e57575, 4.58:1) for
exactly this.

axe does not catch it: it has no text node to measure on an <i> icon,
which is how all five instances were styled. Found by walking every
rendered element and comparing its computed colour against its resolved
background.

Feature and contact icons, the testimonial quote mark and two team
links move across. The quote mark also goes from opacity-40 to 60,
since 40% of an already-dim red was close to invisible.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
og:image was the site logo resized to 512px tall, paired with
twitter:card=summary_large_image. Platforms crop that to roughly 1.91:1
and render it large, so a transparent mark arrived floating on whatever
background the platform chose, at the wrong aspect ratio.

Every page now composes its own 1200x630 card on the brand's dark
ground: the page's own image when it has one — a team portrait, a
package logo, a post's figure — and the CAPRO mark when it does not.
Remote images are skipped deliberately, so a build never depends on
someone else's host being reachable.

Also adds what was missing around it: og:site_name, image width/height
and alt, og:locale:alternate for the other language, article published
and modified times, and explicit twitter:title/description rather than
leaving them to fall back.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every card's call to action reads "Read more", so tabbing through the
news or portfolio list gives no way to tell them apart. The post title
now follows it in a screen-reader-only span.

The card image was built at 300px and stretched to roughly 400 by
w-full, so it was upscaled on every screen and soft on high-density
ones. It now ships 1x and 2x sources with sizes, plus width and height
so the card stops reflowing when the image lands.

Lighthouse on /news/: SEO 92 to 100.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
axe-core passes clean on all 58 pages, but it reports colour-contrast as
"incomplete" wherever text sits over a photograph, and it cannot see focus
indicators at all. Measuring those by hand found four AA failures:

1.4.11 Non-text contrast. The focus ring was the fill red, which is 1.00:1
against the skip link, 1.06:1 against .btn-primary and 2.68:1 against the
page. On the two most important targets on the site it was invisible. White
with a dark halo clears 3:1 on every surface the ring lands on, including
Leaflet's white map controls. `.btn` also used `transition: all`, which
animated the ring in over 200ms, so the first frame of focus was the
browser default; the transition now names its properties.

1.4.3 Contrast. The CTA band composites its photo at 70% rather than 60%,
matching what banner.html already did. The paragraph measured 3.85:1 with
42% of its area below AA; it now measures 5.67:1 with none.

3.2.2 On Input. The language `<select onchange="location=this.value">`
fired on every arrow key, so a keyboard user could never reach the second
language. It is now two links, which also drops an inline-JS dependency and
carries hreflang. Ordered by site.Languages, since AllTranslations is not
sorted and the pair swapped between pages.

2.5.8 Target size. Nav links, the nav group button and the team social
links measured 20-28px tall; all now have a 24px floor.

The byte work is the same kind of gap. banner.html resized its background
to 1600px webp; feature.html and cta.html emitted .RelPermalink, so
/services/ transferred the 3500px originals — 8.2 MB. Leaflet was gated on
site.Params.map, a site-wide param, so 144 KiB of JS shipped to all 58
pages for a map on one. The hero preload fired on every page although
baseof.html renders the banner only on the home page. The logo was a
1624x599 PNG served at 130x48 with width="auto", which is not a valid HTML
width. FontAwesome imported a 'regular' weight no glyph on the site uses.

Favicon declarations were a PNG labelled image/x-icon under the legacy
relation, leaving /favicon.ico to 404 — the only thing costing
best-practices points.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
With the oversized photographs gone, the header logo is what Lighthouse now
picks as the largest contentful paint on most interior pages, and it flagged
the missing priority hint. LCP there is bound by render-blocking CSS rather
than bytes, so this is a small effect; the local score is bimodal between
2.6s and 4.6s either way.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three placeholders that had been rendering literally.

Every team page announced "About Member" in 36px, and its two section
headings read "Posts by Member" / "Publications by Member". All three came
from `index (split .Params.single " ") 1` against the team section's
`single: About Member`. The person's name was meanwhile buried at text-xl
inside the figcaption. The name is now the page's h1, styled like every
other page's section title, with `text-transform: none` so that CSS
`capitalize` does not rewrite "José-Luis Alatorre-Warren" at the hyphen.
The portrait's alt is now empty because the name sits immediately above it;
repeating it made a screen reader say the name twice.

The footer said "Copyright © 2022" on every page of a site whose newest
post is from 2025. The year now comes from site.Lastmod rather than from a
translated string, so it tracks content instead of drifting. CI checks out
with fetch-depth 0, so enableGitInfo gives a real date there.

The home help grid drew its hairlines by painting the container and letting
the cards cover it, so seven items in three columns left cells 8 and 9
filled — a slab that read as a missing card. The hairlines move onto the
cards; empty cells now fall back to the page.

The same grid also broke the hero's promise. It headed each card with
`name` ("Large-scale computing") immediately after a hero saying you do not
need to know the technical name, while `problem` ("The analysis is too big
for your laptop.") sat unused in the same data file — the line /services/
already uses as its headline. Cards now lead with `problem` and demote
`name` to a subtitle. Not another tracked-uppercase label: the theme has
six of those already.

While in team/single.html: the social links derived their aria-label from
the last hyphen-segment of the icon class, so "ti-twitter-alt" announced as
"alt". They now name the person and the host.

axe-core still passes 0 violations across 120 runs, and every page still
has exactly one h1.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
**Contact.** The step the site exists to produce read value-then-label, sat
on the same bg-dark as the team section above it, and said nothing about
what you get for writing. The note moves above the address, the section
moves to bg-grey so it has its own ground, and three reassurances sit under
it. Each is sourced from copy already on the site — the first conversation
is priced at 0 for UiO in content/pricing, and "someone who does the work,
not an account manager" is the team page's own line. No reply-time
commitment: that would be inventing a promise.

**Stable ordering.** people.html, team.html and testimonial.html all ranged
`| shuffle`, so the home strip never matched /team/ and the order changed
on every deploy. Now weight, then title.

**The heading split.** section-title.html cut every title after word one,
which broke the compound in "Open | Source we have built" and left a lone
grey "R" on a tag page with an empty accent span beside it. The split point
is now a caller option (portfolio passes 2), and a single-word title is
accented in full.

**Term pages.** Headed by the bare term, no count, no way out. Now "Tagged
R" / "Filed under MRI" with a post count and a link to all news.

**Portfolio.** The filters had no group label, no pressed state and no
announcement, so pressing one silently removed cards; they now carry
role=group, aria-pressed and a live count, and their styling keys off
aria-pressed rather than a parallel Alpine :class that could drift. The
hover overlay held a second link to the same URL that was invisible on
touch and focusable while transparent — it is decorative now, the title
carries the link, and the overlay also reveals on :focus-within.
Descriptions were `truncate 120`, cutting mid-clause; they take the first
sentence instead.

**Testimonials.** The nav buttons sat at left/right: -20px, on top of the
first and last card's text below ~1480px. They move above the track, they
disable at the ends instead of scrolling into nothing, and the step is
measured from a real card rather than a hardcoded 392px.

**Hierarchy.** .section-title h1 and h2 were the same size, so page title
and section title were indistinguishable. Prose h2/h3/h4 now differ in size
and colour and carry top margin; they were all teal and glued to the
paragraph above.

**The chart.** content/skill/growth.png was six curves over dashed
gridlines with no axes, labels or units, beside the list of tools we
actually use, on a site whose product is trustworthy data. Removed; the
list takes the full width in three columns.

**Side-stripe.** .svc__deliver was a 2px red left border, the one genuine
instance of the pattern in the theme. It is a bordered, tinted callout now.
(.icon-box keeps its 2px sides — those are the hexagon's edges, not an
accent stripe.)

**English on a bilingual site.** 404.html and the whole ORCID publications
UI were hardcoded English. Both translated; 404 also stops being a dead end
and leads with the message rather than the status code.

**Card images.** `img.w-full` stretched a 262x302 source across a 400px
card. Capped at the intrinsic width.

axe-core: 0 violations across 120 runs. Every page has exactly one h1.
Desktop Lighthouse 99-100 across performance, a11y, best practices and SEO.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The services answer "can you help with my problem". They do not answer "do
you do the specific thing I came for", and that is how most would-be clients
arrive — asking about MR-based research, or about Nettskjema, by name.

CAPRO_services.docx frames GOAT, MRI, statistical analysis and Bevex as four
pillars. They are not a service taxonomy: two are named products, one is a
research domain, and one is already the "Processing and analysis" service
under a different name. Making them the spine would leave work that fits none
of the four homeless.

So they go in as a second layer instead. The seven problems stay the spine;
a short block under them names the things a visitor already has a word for,
on both the landing page and /services/. Nettskjema is in that block although
the document does not mention it, because it is the one name clients were
reported to ask about most.

Two of the document's claims are not ours to make yet, and are not made here:

- We do not offer MR scanning. The document describes collection through
  LCBC's MRI-trained staff at Oslo University Hospital; that is their
  capacity, not a CAPRO service. The card starts from data that already
  exists, whoever collected it.
- Bevex is not advertised. It is in testing, beta is expected in spring 2027,
  and a site should not sell what it cannot deliver. The card describes what
  we can do today — build browser-based experiments in JavaScript — and
  mentions the platform as in development, with no date.

Also fixes a bug in this branch's own CSS: markdownify returns text without
its wrapping <p>, so `.svc__deliver p` never matched and "What you get"
rendered unstyled. The paragraph is now written in the template.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The page said "Open source we have built" and listed four things. The
organisation has twelve worth showing: uiothemes, tsdrtools, neuromat,
ebrains.kg and nva in R, jsPsych Studio and the Nettskjema data inspector on
the web, and the R project-management workshop materials. Someone judging
whether we work in the open was judging us on a third of the evidence.

The reason the rest were missing is that the card template required a local
image resource, and only one of the new entries ships a logo. Rather than hunt
for or invent logos, the image panel goes: each card is now the categories,
the linked name and a sentence. The filter chips above already carried the
same categories, so they are not new information — they are the anchor the
card lost with the logo. Two new categories, Web apps and Teaching, since
R-packages and Analyses did not cover what was being added.

Four logo files are deleted with the panel. Nothing referenced them any more,
and this branch has already been removing bytes that ship without being used.

Also fixes the blurb fallback: .Plain returns the rendered HTML's entities,
so "Norway's" reached the card as the literal "&rsquo;" once an entry had an
apostrophe in it. None of the original four did.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`--panicOnWarning` turns the Hugo 0.156 deprecation of `.Site.Languages`
into a hard error, so the strict build in CI fails before it renders the
taxonomy pages. Both language switchers used it, for one property: the
ordering by configured weight, which `AllTranslations` does not give.

`hugo.Sites` is ordered the same way, so the walk is unchanged apart from
reaching the code through `.Language.Lang`. Verified the switcher still
renders English before Norsk on both language trees, with `aria-current`
on the right entry.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two sections sat on pages whose subject they did not match.

The testimonials were the closing section of /portfolio/, under the heading
"Open source we have built". The quotes are about working with us on projects
— a database built over fifteen years of collection, workshops, a data
structure someone can finally use — not about released code. They move to
/services/, straight after "What working with us is like", where they are the
evidence for the claim immediately above them.

The CTA asks "Not sure your problem is on the list?" and invites you to
describe the problem in ordinary words. On /services/ that list is right
there. On /pricing/ there is no list, and the page already closes on its own
ask — "You can always ask what something would cost before committing to
anything" — so the block was both a non sequitur and a second ask. It goes.

/portfolio/ now ends on the projects, which is what a reader came to that page
for.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Same mismatch as /pricing/: "Not sure your problem is on the list?" after a
page about who works here, where there is no list. The skills section already
closes on its own invitation — "If something you use is not on this list, ask
anyway" — so the page keeps an ask, and a better-aimed one.

The CTA now appears only on /services/, which is the page its copy was
written for.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The page was flat for structural reasons, not stylistic ones. Seven items
rendered with identical geometry, one hairline between each, nothing larger
than 1.9rem and nothing smaller than 0.72rem, and in seven screens of scroll
the only colour was a red icon and a 7%-red box.

Three things were scaffolding rather than information:

- The numbers. The old comment said it outright — "the number is rhythm, not
  information, the items are not a sequence and nothing refers to them by
  number". Rhythm is what this commit gets from the layout instead.
- The "What you get" label. Seven of them, and the box under each made the
  heaviest element on the page also the most repetitive, so the emphasis
  stopped registering as emphasis.
- The tracked-uppercase category. Two eyebrows per item, fourteen down the
  page. The category stays, in sentence case, for the reader who knows the
  term; it no longer competes with the problem above it.

What replaces them:

- The problem statement is the one piece of scale, up to 3.25rem, with the
  measure capped at 19ch so it breaks into two or three lines and reads as a
  statement rather than a table row.
- Items alternate which edge they sit on above 900px, and the hairline under
  each is only as wide as the item, so the stagger is visible before any of
  the text is read.
- The payoff is the largest body text in the item and the only teal on the
  page, marked with an arrow rather than a label and a filled box.

Gold (`--color-tertiary`) stays unused. It is defined in the tokens and
appears nowhere on the site; introducing it on one page would orphan it.

Checked at 1280 and 390, both languages. Contrast holds: the symptom text is
4.9:1 on the section background, the teal payoff and the category well above.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant