/* The TerraNovita website. Reads only the design system's tokens, from tokens.css; numbers without
   a unit are positions on the career graph's own grid of 1180 by 450. */

:root { color-scheme: light dark; scroll-padding-top: var(--header-height, 0px); }
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body {
  display: flex; flex-direction: column;
  background: var(--color-surface); color: var(--color-ink); font: var(--type-body);
}

h1, h2, h3, p { margin: 0; }
h2 { font: var(--type-h2); color: var(--color-ink-strong); margin-bottom: var(--space-48); }
h3 { font: var(--type-h3); color: var(--color-ink-strong); margin-bottom: var(--space-16); }
p + p { margin-top: var(--space-16); }
code { font: var(--type-code); }
img { display: block; max-width: 100%; height: auto; }

a { color: var(--color-link); text-underline-offset: var(--space-4); }
a:hover { color: var(--color-link-hover); }
:focus-visible { outline: var(--focus-width) solid var(--color-focus); outline-offset: var(--focus-offset); }

.visually-hidden { position: absolute; width: 1px; height: 1px; margin: 0; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.skip-link {
  position: absolute; left: var(--space-16); top: var(--space-16); z-index: var(--z-dialog);
  padding: var(--space-12) var(--space-16); background: var(--color-surface-raised); transform: translateY(-200%);
}
.skip-link:focus { transform: none; }

/* Header */

.site-header {
  position: sticky; top: 0; z-index: var(--z-header);
  display: flex; align-items: center; gap: var(--space-32);
  padding: var(--space-12) var(--layout-gutter);
  background: var(--color-surface-header); backdrop-filter: blur(var(--blur-header));
  border-bottom: var(--border-width) solid var(--color-border-subtle);
}
.wordmark {
  margin-right: auto; display: inline-flex; align-items: center; gap: var(--space-8);
  min-height: var(--size-target); text-decoration: none;
}
.wordmark-text { font: var(--type-logo); letter-spacing: var(--tracking-logo); color: var(--color-ink-strong); }
.mark-on-dark { display: none; }
:root[data-theme="dark"] .mark-on-light { display: none; }
:root[data-theme="dark"] .mark-on-dark { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .mark-on-light { display: none; }
  :root:not([data-theme="light"]) .mark-on-dark { display: block; }
}

.site-nav { display: flex; gap: var(--space-32); }
.site-nav a { position: relative; display: inline-flex; align-items: center; min-height: var(--size-target); font: var(--type-ui); color: var(--color-ink); text-decoration: none; }
.site-nav a::after {
  content: ""; position: absolute; left: 0; bottom: 0; width: 0; height: var(--border-width-strong);
  background: linear-gradient(90deg, var(--color-line-active), var(--color-highlight));
  transition: width var(--duration-base) var(--easing-standard);
}
.site-nav a:hover::after, .site-nav a[aria-current="true"]::after { width: 100%; }
.site-nav a[aria-current="true"] { color: var(--color-link); }
/* A menu item with pages of its own: its link opens the section's front page, and a chevron button
   beside it opens the list of its pages, dropping below it. */
.nav-group { position: relative; display: inline-flex; align-items: center; gap: var(--space-4); }
/* The button keeps a full tap target, and reaches into the gap after it by the space beside its icon,
   so the chevron stands the menu's own gap from the next link. */
.subnav-toggle {
  display: inline-grid; place-items: center; min-width: var(--size-target); min-height: var(--size-target);
  margin-right: calc((var(--size-icon-sm) - var(--size-target)) / 2);
  padding: 0; background: none; border: 0; border-radius: var(--radius-field); color: var(--color-ink); cursor: pointer;
}
.subnav-toggle:hover { color: var(--color-ink-strong); }
/* The underline runs under the link and its chevron together: the group ends at the chevron's edge. */
.nav-group > a::after { content: none; }
.nav-group::after {
  content: ""; position: absolute; left: 0; bottom: 0; width: 0; height: var(--border-width-strong);
  background: linear-gradient(90deg, var(--color-line-active), var(--color-highlight));
  transition: width var(--duration-base) var(--easing-standard);
}
.nav-group:hover::after, .nav-group:has(> a[aria-current="true"])::after { width: 100%; }
.chevron-icon {
  width: var(--size-icon-sm); height: var(--size-icon-sm);
  fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  transition: transform var(--duration-base) var(--easing-standard);
}
.subnav-toggle[aria-expanded="true"] .chevron-icon { transform: rotate(180deg); }
.subnav {
  position: absolute; top: 100%; left: 0; min-width: 100%; margin: 0; padding: var(--space-8) var(--space-16);
  list-style: none; background: var(--color-surface-raised); border: var(--border-width) solid var(--color-border-subtle);
  border-radius: var(--radius); box-shadow: var(--shadow-hover);
}
.subnav[hidden] { display: none; }
.subnav a { white-space: nowrap; }
/* Home repeats the wordmark's link, so it gives way first where the header's row runs out of room:
   the row needs about 1410 pixels with it, and 1335 without, Assignments being the longest last link. */
@media (max-width: 1439.98px) { .site-nav .nav-home { display: none; } }
.menu-toggle {
  display: none; min-height: var(--size-target); padding: 0 var(--space-16); cursor: pointer;
  font: var(--type-ui); color: var(--color-ink-strong); background: none;
  border: var(--border-width) solid var(--color-border-strong); border-radius: var(--radius);
}

/* The branch switch */

.view-switch { display: inline-flex; align-items: center; margin-left: var(--space-32); }
.view-switch-track {
  position: relative; display: grid; grid-template-columns: repeat(3, 1fr); padding: var(--space-4);
  border: var(--border-width) solid var(--color-border-strong); border-radius: var(--radius-pill);
  background: var(--color-surface-subtle);
}
/* The thumb is one column wide and slides one column per branch: consultancy, main, products. */
.view-switch-track::before {
  content: ""; position: absolute; top: var(--space-4); bottom: var(--space-4); left: var(--space-4);
  width: calc((100% - var(--space-4) * 2) / 3); border-radius: var(--radius-pill);
  background: var(--color-action); box-shadow: var(--shadow-subtle);
  transition: transform var(--duration-base) var(--easing-standard);
}
:root[data-view="projects"] .view-switch-track::before { transform: translateX(100%); }
:root[data-view="products"] .view-switch-track::before { transform: translateX(200%); }
/* Each label is wide enough for the branch icon and the longest name, eleven characters of code
   type, so the switch keeps its width whichever side is chosen. The names set at caption size in
   the code face, with tight padding, so the three fit compactly. */
.view-switch button {
  position: relative; display: inline-flex; align-items: center; justify-content: center; gap: var(--space-4);
  font: var(--type-caption); font-family: var(--font-mono); color: var(--color-ink-muted);
  background: none; border: 0; cursor: pointer;
  min-height: var(--size-target); min-width: calc(11ch + var(--size-icon-sm) + var(--space-4) + var(--space-12) * 2);
  padding: 0 var(--space-12); border-radius: var(--radius-pill);
  transition: color var(--duration-base) var(--easing-standard);
}
.view-switch button:hover { color: var(--color-ink-strong); }
.view-switch button[aria-pressed="true"] { color: var(--color-on-action); }
/* The branch icon marks the branch the visitor can switch to, so only the unchosen label has it. It
   is Lucide's git-branch, drawn in the label's own colour. */
.branch-icon {
  flex: none; width: var(--size-icon-sm); height: var(--size-icon-sm);
  fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
.view-switch button[aria-pressed="true"] .branch-icon { display: none; }

/* Buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--size-target); padding: var(--space-12) var(--space-28);
  font: var(--type-button); text-decoration: none; border-radius: var(--radius);
  border: var(--border-width) solid transparent; cursor: pointer;
  transition: background-color var(--duration-base) var(--easing-standard),
    transform var(--duration-base) var(--easing-standard), box-shadow var(--duration-base) var(--easing-standard);
}
.btn-primary { background: var(--color-action); color: var(--color-on-action); box-shadow: var(--shadow-subtle); }
.btn-primary:hover { background: var(--color-action-hover); color: var(--color-on-action); box-shadow: var(--shadow-hover); transform: translateY(calc(var(--motion-lift-sm) * -1)); }
.btn-on-hero { color: var(--color-on-hero); border-color: var(--color-on-hero-border); }
.btn-on-hero:hover { color: var(--color-on-hero); background: var(--color-on-hero-subtle); }
.btn-large { font: var(--type-button-large); padding: var(--space-16) var(--space-40); }

/* The horizontal track */

.track-frame { position: relative; flex: 1; min-height: 0; display: flex; }
/* No scroll snapping: the browser's snaps the moment a swipe ends. The script settles the track on
   the nearer panel instead, after a pause. */
.track { position: relative; flex: 1; display: flex; overflow-x: auto; overflow-y: hidden; scroll-behavior: smooth; }
.panel {
  position: relative; flex: 0 0 100%; overflow-y: auto;
  background: var(--color-surface); background-origin: border-box;
}
/* A band for the strip's git line: at the bottom of the panels before the career graph, at the top
   of those after it, and none on the graph's own panel. It is a transparent border the panel's
   ground runs under, while its content scrolls clear of it. */
.panel[data-band="bottom"] { border-bottom: var(--space-80) solid transparent; }
.panel[data-band="top"] { border-top: var(--space-80) solid transparent; }
.panel[data-band="top"] .panel-inner { padding-top: var(--space-40); }
.panel-subtle { background-color: var(--color-surface-subtle); }
/* A branch hides the other branches' work panels, and the menu their links. */
.panel[hidden], .site-nav a[hidden] { display: none; }
/* Each panel's ground fades into the next one's near its right edge; the script names the next. */
.panel:not(.panel-hero) { background-image: linear-gradient(90deg, transparent 70%, var(--next-ground, transparent)); }
/* While the track moves sideways, the panels' own scrollbars turn invisible, so no bar stands in a
   seam. The gutter stays, so nothing shifts. */
.track.is-moving .panel { scrollbar-color: transparent transparent; }
.panel-inner {
  position: relative; z-index: 2; max-width: var(--layout-max-width); margin: 0 auto;
  padding: var(--layout-desktop-padding) calc(var(--layout-gutter) + var(--size-target));
  transition: opacity var(--duration-enter) var(--easing-standard), transform var(--duration-enter) var(--easing-standard);
}
.panel:not(.is-seen) .panel-inner { opacity: 0; transform: translateY(var(--motion-rise)); }
.measure { max-width: var(--layout-measure); margin-bottom: var(--space-40); }

.track-step {
  position: absolute; top: 50%; z-index: var(--z-header); transform: translateY(-50%);
  width: var(--size-target); height: var(--size-target); border-radius: var(--radius-pill);
  border: var(--border-width) solid var(--color-border-strong); background: var(--color-surface-raised);
  color: var(--color-ink-strong); font: var(--type-button); cursor: pointer;
}
.track-prev { left: var(--space-8); }
.track-next { right: var(--space-8); }
.track-step[disabled] { opacity: 0; pointer-events: none; }

/* The cue on a panel with more below its fold */

.more-below {
  position: sticky; bottom: var(--space-16); z-index: var(--z-header);
  display: grid; place-items: center; margin: calc(var(--size-target) * -1) calc(var(--layout-gutter) + var(--size-target)) 0 auto;
  width: var(--size-target); height: var(--size-target); border-radius: var(--radius-pill);
  background: var(--color-surface-raised); border: var(--border-width) solid var(--color-border-strong);
  box-shadow: var(--shadow-hover); cursor: pointer;
  opacity: 0; pointer-events: none; transition: opacity var(--duration-base) var(--easing-standard);
}
.more-below::before {
  content: ""; width: var(--space-12); height: var(--space-12); margin-top: calc(var(--space-4) * -1);
  border-right: var(--border-width-strong) solid var(--color-ink-strong);
  border-bottom: var(--border-width-strong) solid var(--color-ink-strong);
  transform: rotate(45deg);
}
.panel.has-more .more-below { opacity: 1; pointer-events: auto; animation: nudge calc(var(--duration-enter) * 3) var(--easing-standard) infinite; }
@keyframes nudge { 50% { transform: translateY(calc(var(--space-4) * -1)); } }

/* The strip: one git line through the track, drawn by the script. It sits above the panels' grounds
   and below their content, styled as the career graph's active lane and joined to it: along the
   bottom band before the graph, along the top band after it. Each panel's start is a commit with a
   ref, and HEAD marks the current panel. At the far right the line rises out of the track into the
   centre of the header's "Get in touch". */

.strip { position: absolute; top: 0; left: 0; height: 100%; z-index: 1; pointer-events: none; }
.strip svg, .strip-end { position: absolute; inset: 0; overflow: visible; pointer-events: none; }
.strip-end { width: 100%; height: 100%; }
.site-header > .btn-primary { position: relative; z-index: 1; }
.strip-line { fill: none; stroke: var(--color-line-active); stroke-width: var(--size-line); stroke-linecap: round; }
.strip-line.on-dark { stroke: var(--color-on-hero-border); }
.strip-commit { fill: var(--color-surface); stroke: var(--color-line-active); stroke-width: var(--border-width-strong); }
.strip-commit.on-dark { fill: var(--color-hero-start); stroke: var(--color-on-hero-border); }
.strip-milestone { fill: var(--color-marker); stroke: var(--color-surface); stroke-width: var(--border-width-strong); }
.strip-milestone.on-dark { fill: var(--color-on-hero); stroke: var(--color-hero-start); }
.strip-milestone.is-head { fill: var(--color-action); }
/* A ref is a plain label in code type, like a branch name in a log. The current panel's becomes one
   filled tag that reads "HEAD → name". */
.strip-ref {
  position: absolute; bottom: calc(var(--space-80) * 0.35 + var(--space-12)); transform: translateX(-50%);
  white-space: nowrap; padding: var(--space-4) var(--space-12); border-radius: var(--radius-pill);
  font: var(--type-caption); font-family: var(--font-mono); color: var(--color-ink-muted);
  transition: background-color var(--duration-base) var(--easing-standard), color var(--duration-base) var(--easing-standard);
}
.strip-ref.on-dark { color: var(--color-on-hero); }
.strip-ref-top { bottom: auto; top: calc(var(--space-80) * 0.35 + var(--space-12)); }
.strip-ref-merge { bottom: auto; transform: translate(calc(var(--space-12) * -1), calc(-100% - var(--space-12))); }
.strip-ref-head { display: none; }
.strip-ref.is-head { background: var(--color-action); color: var(--color-on-action); box-shadow: var(--shadow-subtle); }
.strip-ref.is-head .strip-ref-head { display: inline; }
/* The refs sit in their own layer above the content, so HEAD can be clicked even inside the graph;
   it leads to the next panel. */
.strip-refs { position: absolute; top: 0; left: 0; height: 100%; z-index: 3; pointer-events: none; }
.strip-ref.is-next { pointer-events: auto; cursor: pointer; }
.strip-ref.is-next:hover { background: var(--color-action-hover); }
/* A pulse of light that leaves HEAD along the line now and then: a white bead, a little taller than
   the line so it shines over its edges, a thin tail fading back through the highlight, and a glow,
   so it shows on a line of its own colour too. */
/* The script moves the bead along the line's path and turns the pulse around it. */
.strip-pulse-path { fill: none; stroke: none; }
.strip-pulse {
  position: absolute; left: 0; top: 0; width: var(--space-48); height: var(--space-12);
  margin: calc(var(--space-12) / -2) 0 0 calc((var(--space-48) - var(--space-8)) * -1);
  transform-origin: calc(100% - var(--space-8)) 50%;
  background:
    radial-gradient(circle at calc(100% - var(--space-8)) 50%, var(--color-on-dark) 0 var(--space-4), transparent var(--space-8)),
    linear-gradient(90deg, transparent, var(--color-highlight) 55%, var(--color-on-dark)) center / 100% var(--space-4) no-repeat;
  filter: drop-shadow(0 0 var(--space-4) var(--color-on-dark)) drop-shadow(0 0 var(--space-16) var(--color-highlight));
  opacity: 0; pointer-events: none;
}

/* Panel titles with the old site's service icons */

.panel-title { display: flex; align-items: center; gap: var(--space-20); margin-bottom: var(--space-48); }
.panel-title h2 { margin: 0; }
.panel-kicker { font: var(--type-ui); color: var(--color-ink-muted); margin-bottom: var(--space-4); }
:root[data-view="projects"] .panel-kicker { font: var(--type-code); text-transform: uppercase; letter-spacing: var(--space-4); }
.badge {
  display: grid; place-items: center; flex: none;
  width: calc(var(--size-target) * 1.5); height: calc(var(--size-target) * 1.5);
  border-radius: var(--radius-pill); background: var(--color-plate);
  border: var(--border-width-strong) solid var(--color-spot-teal); box-shadow: var(--shadow-subtle);
}
.badge img { width: 60%; height: auto; }
.badge-small { width: var(--size-target); height: var(--size-target); border-color: var(--color-spot-orange); }
/* The products badge: a sprout under a warm sun, edged in the products branch's green. */
.badge-products { border-color: var(--color-branch-products); }
.project-intro { display: flex; gap: var(--space-20); align-items: flex-start; }

/* Hero */

.panel-hero {
  background: linear-gradient(135deg, var(--color-hero-start), var(--color-hero-end));
  background-origin: border-box;
  color: var(--color-on-hero); display: flex; align-items: center; overflow: hidden;
}
.panel-hero .panel-inner { width: 100%; }
.hero-inner h1 { font: var(--type-h1); color: var(--color-on-hero); max-width: 14em; margin-bottom: var(--space-24); }
.eyebrow { font: var(--type-ui); color: var(--color-on-hero); margin-bottom: var(--space-16); }
.eyebrow::before {
  content: ""; display: inline-block; width: var(--space-40); height: var(--size-line-quiet);
  margin-right: var(--space-12); vertical-align: middle; background: var(--color-highlight); border-radius: var(--radius-pill);
}
.lead { max-width: var(--layout-measure); color: var(--color-on-hero); }
.actions { display: flex; flex-wrap: wrap; gap: var(--space-12); margin-top: var(--space-32); }
.panel-hero :focus-visible { outline-color: var(--color-on-hero-focus); }

.hero-deco { position: absolute; inset: 0; pointer-events: none; }
/* The first seam's circles sit in a layer of the track across the hero's right edge, so a few spill
   into the next panel. The script places the layer, centred on the seam, and lets the circles drift
   at their own pace as the track moves. */
.seam-shapes { position: absolute; top: 0; height: 100%; z-index: 1; pointer-events: none; }
.seam-shapes span {
  position: absolute; border-radius: var(--radius-pill); border: var(--size-line-quiet) solid var(--color-highlight); opacity: 0.85;
  animation: float calc(var(--duration-enter) * 12) var(--easing-standard) infinite alternate;
}
.seam-shapes span:nth-child(even) { animation-delay: -3s; }
.seam-shapes span:nth-child(1) { width: var(--space-80); height: var(--space-80); left: 8%; top: 22%; }
.seam-shapes span:nth-child(2) { width: var(--space-32); height: var(--space-32); left: 22%; top: 64%; border-color: var(--color-spot-orange); }
.seam-shapes span:nth-child(3) { width: var(--space-16); height: var(--space-16); left: 54%; top: 76%; background: var(--color-spot-teal); border-color: var(--color-spot-teal); }
.seam-shapes span:nth-child(4) { width: var(--space-48); height: var(--space-48); left: 34%; top: 36%; border-color: var(--color-spot-teal); }
.seam-shapes span:nth-child(5) { width: var(--space-24); height: var(--space-24); left: 60%; top: 52%; border-color: var(--color-spot-berry); }
.seam-shapes span:nth-child(6) { width: var(--space-12); height: var(--space-12); left: 66%; top: 28%; background: var(--color-highlight); border: 0; }
.hero-deco span {
  position: absolute; border-radius: var(--radius-pill);
  border: var(--size-line-quiet) solid var(--color-highlight); opacity: 0.85;
  animation: float calc(var(--duration-enter) * 12) var(--easing-standard) infinite alternate;
}
.hero-deco span:nth-child(1) { width: var(--space-120); height: var(--space-120); right: 8%; top: 14%; }
.hero-deco span:nth-child(2) { width: var(--space-48); height: var(--space-48); right: 24%; top: 62%; border-color: var(--color-spot-orange); animation-delay: -2s; }
.hero-deco span:nth-child(3) { width: var(--space-24); height: var(--space-24); right: 14%; top: 72%; background: var(--color-spot-teal); border-color: var(--color-spot-teal); animation-delay: -4s; }
.hero-deco span:nth-child(4) { width: var(--space-80); height: var(--space-80); right: 32%; top: 18%; border-color: var(--color-on-hero-border); animation-delay: -1s; }
.hero-deco span:nth-child(5) { width: var(--space-16); height: var(--space-16); right: 6%; top: 52%; background: var(--color-highlight); animation-delay: -3s; }
.hero-deco span:nth-child(6) { width: var(--space-32); height: var(--space-32); right: 40%; top: 74%; border-color: var(--color-spot-berry); animation-delay: -5s; }
.hero-deco span:nth-child(7) { width: var(--space-12); height: var(--space-12); right: 20%; top: 8%; background: var(--color-on-hero); border: 0; animation-delay: -6s; }
@keyframes float { to { transform: translateY(calc(var(--space-24) * -1)) rotate(12deg); } }

/* The three views: each shows only its own words */

:root:not([data-view="consultancy"]) .for-consultancy,
:root:not([data-view="projects"]) .for-projects,
:root:not([data-view="products"]) .for-products { display: none; }

/* Grid and cards */

.grid { display: grid; gap: var(--layout-gutter); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.card {
  display: flex; flex-direction: column; position: relative;
  background: var(--color-surface-raised); border: var(--border-width) solid var(--color-border-subtle);
  border-radius: var(--radius); padding: var(--space-32);
  transition: transform var(--duration-base) var(--easing-standard), box-shadow var(--duration-base) var(--easing-standard);
}
.spot-cards .card { --spot: var(--color-spot-teal); border-top: var(--size-line) solid var(--spot); }
.spot-cards .card:nth-child(4n+2) { --spot: var(--color-spot-orange); }
.spot-cards .card:nth-child(4n+3) { --spot: var(--color-spot-berry); }
.spot-cards .card:nth-child(4n+4) { --spot: var(--color-line-active); }
.card p:not(.tech) { font: var(--type-small); }
.tech { font: var(--type-small); color: var(--color-ink-muted); margin-top: auto; padding-top: var(--space-16); }
.card-project { padding: var(--space-20); }
.card-project .art { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; border-radius: var(--radius-field); margin-bottom: var(--space-16); }
/* A placeholder for a product or a page not yet written: a plain dashed frame that claims nothing. */
.card-placeholder, .spot-cards .card-placeholder { border: var(--border-width) dashed var(--color-border-subtle); }
.card-placeholder h3 { color: var(--color-ink-muted); }
.art-placeholder { display: block; background: var(--color-placeholder); }
.logo-plate {
  display: grid; place-items: center; align-self: flex-start;
  background: var(--color-plate); border-radius: var(--radius-field);
  padding: var(--space-4) var(--space-8); margin-bottom: var(--space-16);
}
.logo-plate img { width: calc(var(--size-card) * 0.7); height: auto; }

/* The career graph */

.legend { display: flex; flex-wrap: wrap; gap: var(--space-24); margin-bottom: var(--space-24); font: var(--type-small); color: var(--color-ink-muted); }
.legend-item { display: inline-flex; align-items: center; gap: var(--space-8); }
/* The legend's marks are the graph's milestones in small, coloured by the same rules. */
.legend-dot, .legend-ring, .legend-square { width: var(--size-icon-sm); height: var(--size-icon-sm); border-radius: var(--radius-pill); }
.legend-dot { background: var(--color-branch-consultancy); }
:root[data-view="consultancy"] .legend-dot { background: var(--color-line-active); }
.legend-ring { border: var(--size-line-quiet) solid var(--color-line-quiet); }
:root[data-view="projects"] .legend-ring { border-color: var(--color-marker-project); }
.legend-square { border-radius: calc(var(--radius-field) / 2); border: var(--size-line-quiet) solid var(--color-branch-products); }
:root[data-view="products"] .legend-square { border-color: var(--color-line-active); }
.legend-merge { width: var(--space-32); height: var(--size-line-quiet); border-radius: var(--radius-pill); background: linear-gradient(90deg, var(--color-spot-teal), var(--color-spot-orange)); }

#career .panel-inner { padding-top: var(--space-40); }
#career h2 { margin-bottom: var(--space-16); }
.graph-note { margin: var(--space-60) 0 0; }
/* The graph never draws smaller than 960 by 480. The floor sits on the width, because the aspect
   ratio derives the height from it. On a screen narrower than that, the career panel grows to hold
   the whole graph, and the track scrolls through it like any other panel. */
.graph { position: relative; aspect-ratio: 1180 / 590; min-width: calc(var(--layout-max-width) * 0.8); margin-top: var(--space-16); }
/* Its own formatting context, so the graph's top margin adds to the legend's instead of merging. */
.graph-scroll { display: flow-root; }
#career { flex: 0 0 auto; min-width: 100%; }
/* The drawing lies over the lane labels, so a label's dotted stem runs under any dot on its lane;
   the cards and merge chips lie over the drawing, and clicks pass through it to the labels. */
.graph-lines { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.graph-lines path { fill: none; stroke-linecap: round; transition: stroke var(--duration-base) var(--easing-standard), stroke-width var(--duration-base) var(--easing-standard); }
.lane { stroke: var(--color-line-quiet); stroke-width: var(--size-line-quiet); }
/* A trunk is main up to where a branch is cut: consultancy's at 170, products' at 810. On its
   branch's view it is drawn active, so the line that enters main from the strip runs unbroken into
   the branch. The two branches keep their colours in every view, quiet unless chosen: consultancy
   the brand blue, products the logo green. */
.lane-trunk { display: none; }
:root[data-view="consultancy"] .lane-trunk-consultancy,
:root[data-view="products"] .lane-trunk-products { display: inline; }
.lane-consultancy { stroke: var(--color-branch-consultancy); }
.lane-products { stroke: var(--color-branch-products); }
:root[data-view="consultancy"] .lane-consultancy,
:root[data-view="consultancy"] .lane-trunk-consultancy,
:root[data-view="projects"] .lane-main,
:root[data-view="products"] .lane-trunk-products,
:root[data-view="products"] .lane-products { stroke: var(--color-line-active); stroke-width: var(--size-line); }
.stems path { stroke: var(--color-line-quiet); stroke-width: var(--border-width-strong); stroke-dasharray: 2 6; }
.merge { stroke-width: var(--size-line-quiet); }
.merge-teal { stroke: var(--color-spot-teal); }
.merge-orange { stroke: var(--color-spot-orange); }
.arrow-teal, .packet-teal { fill: var(--color-spot-teal); }
.arrow-orange, .packet-orange { fill: var(--color-spot-orange); }
.packet { stroke: var(--color-surface-subtle); stroke-width: var(--border-width-strong); }
.commits circle { fill: var(--color-surface-subtle); stroke: var(--color-line-quiet); stroke-width: 3; }
.commits .on-lane-consultancy { stroke: var(--color-branch-consultancy); }
.commits .on-lane-products { stroke: var(--color-branch-products); }
:root[data-view="consultancy"] .commits .on-lane-consultancy,
:root[data-view="consultancy"] .commits .on-trunk-consultancy,
:root[data-view="projects"] .commits .on-lane-main,
:root[data-view="products"] .commits .on-trunk-products,
:root[data-view="products"] .commits .on-lane-products { stroke: var(--color-line-active); }
/* Each lane has its own milestone shape in every view: an assignment a filled dot, a project a
   ring, a product a square outline. A milestone takes the colour of the line it sits on: its branch's
   colour, the active line's when that branch is chosen, and main's grey for a project, or the
   trunk's colour where a chosen branch draws main. Only a chosen main gives its rings a colour of
   their own, to stand out on the active line. */
.milestone { rx: 12px; fill: var(--color-branch-consultancy); stroke: var(--color-surface-subtle); stroke-width: 3; }
:root[data-view="consultancy"] .milestone:not(.milestone-project, .milestone-product) { fill: var(--color-line-active); }
.milestone-project { fill: var(--color-surface-subtle); stroke: var(--color-line-quiet); stroke-width: 5; }
:root[data-view="consultancy"] .milestone-project.on-trunk-consultancy,
:root[data-view="products"] .milestone-project.on-trunk-products { stroke: var(--color-line-active); }
:root[data-view="projects"] .milestone-project { stroke: var(--color-marker-project); }
.milestone-product { rx: calc(var(--radius-field) / 2); fill: var(--color-surface-subtle); stroke: var(--color-branch-products); stroke-width: 5; }
:root[data-view="products"] .milestone-product { stroke: var(--color-line-active); }
.graph-lines .lane-name { font: var(--type-code); fill: var(--color-ink-strong); }

.commit-card, .merge-chip, .lane-switch {
  position: absolute; left: calc(var(--x) / 1180 * 100%); top: calc(var(--y) / 590 * 100%);
}
.commit-card, .merge-chip { z-index: 1; }
/* An assignment's card hangs above the consultancy lane, its --y: the card's bottom sits a fixed gap
   above the line at any size, so the card never crowds the line when the graph draws smaller. The
   graph's top margin holds the card's top at the smallest size. */
.commit-card:not(.commit-card-project) { top: auto; bottom: calc((590 - var(--y)) / 590 * 100% + var(--space-24)); }
.pos-vrt { --x: 282; --y: 150; }
.pos-medialaan { --x: 420; --y: 150; }
.pos-vanin { --x: 558; --y: 150; }
.pos-telenet { --x: 696; --y: 150; }
.pos-isabel { --x: 834; --y: 150; }
.pos-corilus { --x: 972; --y: 150; }
.pos-auric { --x: 1110; --y: 150; }
.pos-terraworld { --x: 110; --y: 322; }
.pos-cake { --x: 380; --y: 322; }
.pos-bouncer { --x: 560; --y: 322; }
.pos-sofie { --x: 740; --y: 322; }
.merge-chip-teal { --x: 322; --y: 215; }
.merge-chip-orange { --x: 488; --y: 238; }
.lane-switch-consultancy { --x: 1160; --y: 150; }
.lane-switch-main { --x: 1160; --y: 280; }
.lane-switch-products { --x: 1160; --y: 510; }
.pos-product-1 { --x: 950; --y: 322; }
.pos-product-2 { --x: 1090; --y: 322; }
.commit-card {
  width: calc(128 / 1180 * 100%); transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: stretch; gap: var(--space-8);
  padding: var(--space-8); border-radius: var(--radius); cursor: pointer; text-align: center;
  background: var(--color-surface-raised); border: var(--border-width) solid var(--color-border-subtle);
  color: var(--color-ink-strong); box-shadow: var(--shadow-subtle);
  transition: transform var(--duration-base) var(--easing-standard), box-shadow var(--duration-base) var(--easing-standard);
}
.commit-card:hover { transform: translateX(-50%) translateY(calc(var(--motion-lift) * -1)); box-shadow: var(--shadow-hover); }
.commit-card .logo-plate { align-self: stretch; margin: 0; height: var(--space-48); }
.commit-card .commit-label { min-height: calc(var(--space-20) * 2); display: grid; place-items: center; }
.commit-card .logo-plate img { width: auto; max-width: 100%; max-height: calc(var(--space-48) - var(--space-12)); }
.commit-card .art { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; border-radius: var(--radius-field); }
/* A placeholder on the products branch, until a product takes its place: a plain frame, not a button. */
.commit-card-placeholder { cursor: default; border-style: dashed; box-shadow: none; }
.commit-card-placeholder:hover { transform: translateX(-50%); box-shadow: none; }
.commit-card-placeholder .commit-label { color: var(--color-ink-muted); }
/* Artwork with its title near the top is cropped higher than the centre, so the title stays whole
   and the scene below still shows. */
.art-title { object-position: 50% 25%; }
.commit-label { font: var(--type-ui); line-height: 1.25; }

.merge-chip {
  transform: translate(-50%, -50%); white-space: nowrap;
  padding: var(--space-4) var(--space-12); border-radius: var(--radius-pill);
  background: var(--color-surface-raised); border: var(--border-width-strong) solid var(--color-spot-teal);
  font: var(--type-caption); color: var(--color-ink-strong); box-shadow: var(--shadow-subtle);
}
.merge-chip-orange { border-color: var(--color-spot-orange); }

.lane-switch {
  transform: translate(-100%, 30%); cursor: pointer;
  min-height: var(--size-target); padding: 0 var(--space-16); border-radius: var(--radius-pill);
  font: var(--type-code); color: var(--color-ink-strong); background: var(--color-surface-raised);
  border: var(--border-width-strong) solid var(--color-line-quiet);
}
/* main's label sits above its lane, clear of the product cards that hang below it; products' sits
   a little further below its lane than the others, so the thick line keeps some air above it.
   Two labels between the same two lanes need more height than the graph gives them below its
   widest, so main's label stands to the left of consultancy's, a gap clear of it: consultancy's
   width is its eleven characters in the code face, its padding and its border. */
.lane-switch-main {
  transform: translate(calc(-100% - 11ch - var(--space-16) * 2 - var(--border-width-strong) * 2 - var(--space-12)), -130%);
}
.lane-switch-products { transform: translate(-100%, 45%); }
/* A dotted stem ties each label to its lane, as the cards' stems do: it spans the gap the label's
   offset leaves, up to the lane for a label below it and down for main's above it. */
.lane-switch::before {
  content: ""; position: absolute; left: 50%; bottom: calc(100% + var(--border-width-strong));
  width: var(--border-width-strong); height: calc(var(--size-target) * 0.3); margin-left: calc(var(--border-width-strong) / -2);
  background: repeating-linear-gradient(to bottom, var(--color-line-quiet) 0 var(--border-width-strong), transparent var(--border-width-strong) var(--space-8));
}
.lane-switch-products::before { height: calc(var(--size-target) * 0.45); }
.lane-switch-main::before { bottom: auto; top: calc(100% + var(--border-width-strong)); }
:root[data-view="consultancy"] .lane-switch-consultancy,
:root[data-view="projects"] .lane-switch-main,
:root[data-view="products"] .lane-switch-products { background: var(--color-action); border-color: var(--color-action); color: var(--color-on-action); }

/* The footer: a slim strip under the track, with the copyright and the contact route */

.site-footer {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-16);
  padding: 0 var(--layout-gutter); background: var(--color-surface);
  border-top: var(--border-width) solid var(--color-border-subtle);
  font: var(--type-caption); color: var(--color-ink-muted);
}
.site-footer a {
  display: inline-flex; align-items: center; min-height: var(--size-target);
  color: var(--color-link); font: var(--type-small);
}
.site-footer a:hover { color: var(--color-link-hover); }

/* The 404 page */

.not-found {
  flex: 1; display: grid; place-content: center; justify-items: center; gap: var(--space-24);
  padding: var(--layout-desktop-padding) var(--layout-gutter); text-align: center;
}
.not-found h1 { font: var(--type-h2); color: var(--color-ink-strong); }

/* Dialog */

.detail {
  width: min(var(--layout-measure), calc(100% - var(--layout-gutter) * 2));
  padding: var(--space-32); border: var(--border-width) solid var(--color-border-subtle);
  border-radius: var(--radius); background: var(--color-surface-raised); color: var(--color-ink);
  box-shadow: var(--shadow-dialog);
}
.detail::backdrop { background: var(--color-scrim); }
.detail h3 { padding-right: var(--size-target); }
.detail-body h3 { display: none; }
.detail-art {
  width: 100%; height: auto; max-height: calc(var(--layout-measure) * 0.5); object-fit: cover;
  border-radius: var(--radius-field); margin-bottom: var(--space-16); background: var(--color-placeholder);
}
.detail-art-top { aspect-ratio: 801 / 440; object-position: top; }
.detail-logo { display: inline-grid; padding: var(--space-8) var(--space-16); box-shadow: var(--shadow-subtle); }
.detail-logo img { width: auto; height: var(--space-40); }
.detail-close {
  position: absolute; top: var(--space-12); right: var(--space-12); width: var(--size-target); height: var(--size-target);
  border-radius: var(--radius-pill); border: 0; background: none; color: var(--color-ink-strong); font: var(--type-h3); cursor: pointer;
}

/* The project view: a game studio */

:root[data-view="projects"] .panel:not(.panel-hero) {
  background-image: radial-gradient(var(--color-border-subtle) var(--border-width), transparent 0);
  background-size: var(--space-24) var(--space-24);
}
:root[data-view="projects"] .card,
:root[data-view="projects"] .commit-card,
:root[data-view="projects"] .detail,
:root[data-view="projects"] .merge-chip {
  border: var(--border-width) solid var(--color-border-strong); box-shadow: var(--shadow-subtle);
}
:root[data-view="projects"] .spot-cards .card { border-top: var(--size-line) solid var(--spot); }
:root[data-view="projects"] .card:hover { transform: translate(calc(var(--motion-lift-sm) * -1), calc(var(--motion-lift-sm) * -1)); box-shadow: var(--shadow-hover); }
:root[data-view="projects"] .commit-card:hover { transform: translateX(-50%) translate(calc(var(--motion-lift-sm) * -1), calc(var(--motion-lift-sm) * -1)); }
:root[data-view="projects"] .btn-primary:active,
:root[data-view="projects"] .commit-card:active { transform: translateX(0) translate(var(--motion-lift-sm), var(--motion-lift-sm)); box-shadow: none; }
:root[data-view="projects"] .commit-card:active { transform: translateX(-50%) translate(var(--motion-lift-sm), var(--motion-lift-sm)); }
:root[data-view="projects"] .eyebrow { font: var(--type-code); text-transform: uppercase; letter-spacing: var(--space-4); }
:root[data-view="projects"] .eyebrow::before {
  width: var(--space-12); height: var(--space-20); border-radius: 0; background: var(--color-highlight);
  animation: blink calc(var(--duration-base) * 4) steps(1) infinite;
}
@keyframes blink { 50% { opacity: 0; } }
:root[data-view="projects"] .badge { border-radius: var(--radius-field); }
:root[data-view="projects"] .hero-deco span,
:root[data-view="projects"] .seam-shapes span { border-radius: var(--radius-field); }
:root[data-view="projects"] .hero-deco span:nth-child(odd) { animation-name: bob; }
@keyframes bob { 50% { transform: translateY(calc(var(--space-12) * -1)) rotate(45deg); } }
:root[data-view="projects"] .view-switch-track { border-radius: var(--radius); }
:root[data-view="projects"] .view-switch-track::before { border-radius: var(--radius-field); }

/* The products view: nature. The whole strip lies in dappled light, soft glows of the logo green and
   of lagoon as if the sun came through leaves. They are drawn on the strip's layer, which runs
   across every panel under the content, so no seam cuts a glow off: three tiles of different widths
   repeat along it, each glow fading out well inside its tile, and their mismatch keeps the light
   from looking regular. Its hero's shapes are leaves in the branch green that sway rather than float. */

:root[data-view="products"] .strip {
  background-image:
    radial-gradient(ellipse calc(var(--space-120) * 3) calc(var(--space-120) * 2.5) at 30% 22%,
      color-mix(in srgb, var(--color-highlight) 16%, transparent), transparent 70%),
    radial-gradient(ellipse calc(var(--space-120) * 2.5) calc(var(--space-120) * 2) at 72% 78%,
      color-mix(in srgb, var(--color-branch-products) 10%, transparent), transparent 70%),
    radial-gradient(ellipse calc(var(--space-120) * 3) calc(var(--space-120) * 3) at 50% 45%,
      color-mix(in srgb, var(--color-highlight) 12%, transparent), transparent 70%);
  background-size: calc(var(--layout-max-width) * 0.9) 100%, calc(var(--layout-max-width) * 1.3) 100%,
    calc(var(--layout-max-width) * 1.7) 100%;
  background-repeat: repeat-x;
}
:root[data-view="products"] .hero-deco span,
:root[data-view="products"] .seam-shapes span {
  border-radius: 50% 0; border-color: var(--color-branch-products); animation-name: sway;
}
:root[data-view="products"] .hero-deco span:nth-child(3n),
:root[data-view="products"] .seam-shapes span:nth-child(3n) {
  background: color-mix(in srgb, var(--color-highlight) 55%, transparent); border-color: transparent;
}
:root[data-view="products"] .hero-deco span:nth-child(2),
:root[data-view="products"] .seam-shapes span:nth-child(2) { border-color: var(--color-accent); }
:root[data-view="products"] .hero-deco span:nth-child(7) { background: var(--color-highlight); }
/* Leaves fall every which way: half are mirrored, each lies at its own angle, and some sway the
   other way. The angle is the rotate property, so the sway's transform turns them on top of it. */
:root[data-view="products"] .hero-deco span:nth-child(even),
:root[data-view="products"] .seam-shapes span:nth-child(even) { border-radius: 0 50%; }
:root[data-view="products"] .hero-deco span:nth-child(3n + 1),
:root[data-view="products"] .seam-shapes span:nth-child(3n + 1) { animation-direction: alternate-reverse; }
:root[data-view="products"] .hero-deco span:nth-child(1) { rotate: 24deg; }
:root[data-view="products"] .hero-deco span:nth-child(2) { rotate: -38deg; }
:root[data-view="products"] .hero-deco span:nth-child(3) { rotate: 72deg; }
:root[data-view="products"] .hero-deco span:nth-child(4) { rotate: -12deg; }
:root[data-view="products"] .hero-deco span:nth-child(5) { rotate: 135deg; }
:root[data-view="products"] .hero-deco span:nth-child(6) { rotate: 48deg; }
:root[data-view="products"] .hero-deco span:nth-child(7) { rotate: -80deg; }
:root[data-view="products"] .seam-shapes span:nth-child(1) { rotate: -55deg; }
:root[data-view="products"] .seam-shapes span:nth-child(2) { rotate: 15deg; }
:root[data-view="products"] .seam-shapes span:nth-child(3) { rotate: 100deg; }
:root[data-view="products"] .seam-shapes span:nth-child(4) { rotate: -20deg; }
:root[data-view="products"] .seam-shapes span:nth-child(5) { rotate: 160deg; }
:root[data-view="products"] .seam-shapes span:nth-child(6) { rotate: 35deg; }
@keyframes sway { 50% { transform: translateY(calc(var(--space-12) * -1)) rotate(-14deg); } }

/* Between the breakpoint and a wide screen the header has no room for its links beside the
   three-way branch switch and the invitation: they fold behind the Menu button and open as a row
   under the header. */

@media (min-width: 768px) and (max-width: 1359.98px) {
  .site-header { flex-wrap: wrap; row-gap: 0; }
  .menu-toggle { display: inline-flex; align-items: center; }
  .menu-toggle ~ .site-nav { display: none; order: 5; width: 100%; justify-content: flex-end; padding-bottom: var(--space-8); }
  .site-header.menu-open .menu-toggle ~ .site-nav { display: flex; }
  .site-nav a { white-space: nowrap; }
  .site-nav .nav-home { display: inline-flex; }
}

/* Below the breakpoint: a stacked page */

@media (max-width: 767.98px) {
  body { display: block; height: auto; }
  .site-header { flex-wrap: wrap; gap: var(--space-8) var(--space-12); }
  .site-header > .btn { display: none; order: 5; width: 100%; margin-bottom: var(--space-8); }
  .site-header.menu-open > .btn { display: inline-flex; }
  .menu-toggle { display: inline-flex; align-items: center; order: 2; }
  .view-switch { order: 3; width: 100%; margin-left: 0; }
  .view-switch-track { width: 100%; }
  /* Three names share a phone's width, so they set smaller and without the branch icon. */
  .view-switch button { min-width: 0; padding: 0 var(--space-4); font: var(--type-caption); font-family: var(--font-mono); }
  .branch-icon { display: none; }
  .site-nav { display: none; order: 4; width: 100%; flex-direction: column; gap: 0; }
  .site-header.menu-open .site-nav { display: flex; }
  .site-nav .nav-home { display: inline-flex; }
  /* In the folded column a section's pages list under its link, always open. */
  .nav-group { flex-wrap: wrap; }
  .nav-group::after { content: none; }
  .nav-group > a::after { content: ""; }
  .subnav-toggle { display: none; }
  .subnav, .subnav[hidden] {
    display: block; position: static; width: 100%; padding: 0 0 0 var(--space-16);
    background: none; border: 0; box-shadow: none;
  }
  .track-step { display: none; }
  .track-frame, .track { display: flex; flex-direction: column; overflow: visible; }
  .panel { flex: none; overflow: visible; }
  .panel[data-band] { border-width: 0; }
  .panel[data-band="top"] .panel-inner { padding-top: var(--layout-mobile-padding); }
  .panel:not(.panel-hero) { background-image: none; }
  .strip, .strip-refs, .strip-end, .seam-shapes { display: none; }
  .panel-inner { padding: var(--layout-mobile-padding) var(--layout-gutter); }
  h2 { font: var(--type-h2-mobile); }
  .hero-inner h1 { font: var(--type-h1-mobile); }
  .grid-2 { grid-template-columns: minmax(0, 1fr); }
  .hero-deco, .more-below { display: none; }
  /* The stacked page scrolls down, so here the graph scrolls sideways on its own. The padding holds
     the cards that reach past the graph's edge, and their lift on hover. */
  .graph-scroll { overflow: auto hidden; padding-block: var(--space-12) var(--space-32); }
}

@media (prefers-reduced-motion: reduce) {
  .track { scroll-behavior: auto; }
  *, *::before, *::after { transition-duration: 0s !important; animation: none !important; }
  .packet { display: none; }
  .panel:not(.is-seen) .panel-inner { opacity: 1; transform: none; }
}
