/* OSk3y site layout — page scaffolding only.
   Loaded after theme.css: theme.css carries the component look (nav, buttons,
   cards, inputs, panel) straight from the bound OSk3y design system; this file
   carries the page's geometry and its web-scale type. Every value here resolves
   to an --osk-* token. Nothing is invented.

   RHYTHM: the site runs on the design system's 28px leading unit
   (--osk-web-leading) with a 14px half-step. Line-heights and block margins are
   unit multiples; headings are cap-trimmed so block edges land on baselines. */

:root {
  --leading: var(--osk-web-leading);
  --half: var(--osk-web-half);
  --edge: clamp(20px, 5vw, 72px);        /* page gutter — fluid, per the DS web layout */
  --measure: var(--osk-measure);
}

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body { margin: 0; text-wrap: pretty; }

.wrap { max-width: var(--osk-container); margin: 0 auto; padding: 0 var(--edge); }

/* the masthead paints full width; its contents sit on the wrap's text axis */
.nav { padding-inline: max(var(--edge), calc((100% - var(--osk-container)) / 2 + var(--edge))); }
.nav a { white-space: nowrap; }
/* The narrow label only exists for the phone masthead; see the 480px block. */
.nav-programmes .nav-narrow { display: none; }
/* Below 480px the section links fold away — but Sign in stays. The portal is
   the one destination a phone visitor actually needs, and hiding every link
   left the masthead with no way in at all.

   This comment used to say the folded links keep their place in the footer.
   They do not: the footer is a single copyright line and carries no links at
   all. What actually catches them is the homepage body — #products, #services
   and #programmes are sections on it, Work is linked twice from it, and Contact
   is the Book a call button. That holds on index.html and nowhere else, so on
   work, clients or contact a phone has no route back to those pages. Worth
   fixing with a real footer nav; not fixed here. */
@media (max-width: 480px) {
  /* Sign in and the Clients pill are the two ways in, so both are named here.
     A later rule cannot rescue the pill on source order: :not(.btn):not([href])
     already outweighs any `.nav a.nav-pill` that follows, so the exemption has
     to live in this selector. Match the href on a substring — the source links
     to signin.html and Netlify's pretty URLs serve it as /signin, and the rule
     has to hold either way.

     Fold direct children only. On signin, clients, reset, portal and
     client-portal the brand is a link — `.nav-brand > a[href="index.html"]` —
     and a descendant selector folds that away with the section links. It is
     upright today only because the markup carries an inline
     `display:inline-flex` that outranks a stylesheet `display:none`; delete
     that attribute and five pages lose their home link. The child combinator
     says what the rule means and does not lean on the accident. */
  .nav > a:not(.btn):not(.nav-pill):not([href*="signin"]):not(.nav-programmes) { display: none; }
  /* A bare 14px link is a 28px tap target; the system floor is 44. Padding
     buys the target without touching the type. aria-current keeps its accent
     so the signin page still says "you are here". */
  .nav > a[href*="signin"] { display: inline-flex; align-items: center;
    min-height: var(--osk-hit); }
  .nav > a[href*="signin"]:not([aria-current]) { color: var(--osk-ink); }
  /* Programmes is the fifth item and the masthead was already full at four, so
     it folds its label rather than its link: "Programmes" measures 84px against
     62px of free space at 390px, and "K3Ys" measures 34px.

     The anchor's aria-label reads "K3Ys — Programmes" at every width, and it
     has to contain both. An earlier version set it to "Programmes" alone, which
     made the accessible name stop containing the visible label as soon as this
     rule swapped the text: someone driving the page by voice, looking at a link
     that says K3Ys, saying "K3Ys", would not have reached it. WCAG 2.5.3 is the
     rule and speech input is who it is for. */
  .nav > a.nav-programmes { display: inline-flex; align-items: center;
    min-height: var(--osk-hit); color: var(--osk-ink); }
  .nav-programmes .nav-wide { display: none; }
  .nav-programmes .nav-narrow { display: inline; }
  /* Four items — brand, Sign in, the pill, Book a call — do not fit a phone
     masthead while the brand is the 112px lockup, so it falls back to its
     square mark and the two chips tighten. Nothing is dropped: every
     destination the wide nav offers stays reachable. */
  .nav { gap: 10px; }
  .nav-brand img { content: url("./assets/osk3y-mark.png"); }
  .nav > a.nav-pill { padding: 0 11px; }
  .nav > a.btn { padding: 11px 13px; }
}
/* Under 375px even "K3Ys" does not fit: brand, Sign in, the pill and Book a call
   already spend 328px of a 360px viewport, and the short label plus its gap costs
   44px. Nothing here is worth shrinking to buy 12px, so the link folds again and
   the homepage's own K3Y programmes section stays the route in. */
@media (max-width: 374px) {
  .nav > a.nav-programmes { display: none; }
}

/* — full-width rules fade to transparent over 48px at each end — */
.rule { height: 1px; border: 0; margin: 0;
  background: linear-gradient(to right, transparent, var(--osk-rule-row) 48px calc(100% - 48px), transparent); }

/* — kicker: uppercase, solid 44px accent dash (colour + tracking: theme.css) — */
.kicker { position: relative; display: block; text-transform: uppercase;
  line-height: var(--half); font-variant-numeric: tabular-nums;
  margin: 0 0 calc(var(--leading) - var(--half)); }
.kicker::before { content: ""; position: absolute; left: -64px; top: calc(50% - 0.5px);
  width: 44px; height: 1px; background: var(--osk-accent-text); }
/* below 1280px the gutter drops under the dash's 64px hang — it folds away
   rather than cropping at the viewport edge */
@media (max-width: 1280px) { .kicker::before { display: none; } }

/* — hero — */
.hero { padding: calc(4 * var(--leading)) 0 calc(3 * var(--leading)); }
.display { font-family: var(--osk-font-sans); font-weight: 600;
  font-size: var(--osk-web-display);
  line-height: clamp(49px, 7.13vw, 98px);   /* display leading is ratio-governed (≈1.11) */
  letter-spacing: var(--osk-track-tight);
  margin: 0 0 0 -0.06em;                    /* optical left alignment — Inter's flat-stem bearings */
  color: var(--osk-ink);
  text-box: trim-both cap alphabetic; }
.display .line { display: block; }          /* a display header breaks per sentence */
.hero .sub { font-size: var(--osk-web-body); line-height: var(--leading);
  max-width: var(--measure); color: var(--osk-ink);
  margin: calc(1.5 * var(--leading) - 1cap) 0 0;
  text-box: trim-both cap alphabetic; }
.hero .row { display: flex; gap: var(--osk-space-6); flex-wrap: wrap; margin-top: var(--leading); }

/* — stat band: the site's one saturated section, run full-bleed — */
.stats { background:
    radial-gradient(900px 420px at 85% -40%, rgba(20, 184, 166, 0.22), transparent 64%),
    var(--color-section);
  padding: calc(2.5 * var(--leading)) 0; }
.stats .grid { display: grid; grid-template-columns: repeat(4, auto);
  justify-content: space-between; gap: calc(1.5 * var(--leading)) var(--leading); }
.stat-num { font-family: var(--osk-font-sans); font-weight: 600;
  font-size: clamp(36px, 3.6vw, 52px); line-height: calc(2 * var(--leading));
  color: var(--osk-ink); font-variant-numeric: tabular-nums;
  margin: 0 0 0 -0.055em; text-box: trim-both cap alphabetic; }
.stat-label { font-size: 13px; line-height: var(--half);
  letter-spacing: var(--osk-track-section); text-transform: uppercase;
  color: var(--osk-body); margin: var(--half) 0 0; }

/* — feature rows: numbered, rule-parted, asymmetric — no equal cards — */
.features { padding: calc(3.5 * var(--leading)) 0 calc(2.5 * var(--leading)); }
.feature { display: grid;
  grid-template-columns: minmax(64px, 160px) minmax(0, 420px) minmax(0, 1fr);
  gap: var(--leading) clamp(24px, 4vw, 72px); align-items: baseline;
  padding: calc(1.5 * var(--leading)) 0; }
.feature + .feature { border: 0; position: relative; }
.feature + .feature::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 1px;
  background: linear-gradient(to right, transparent, var(--osk-rule-section) 48px calc(100% - 48px), transparent); }
.f-num { font-family: var(--osk-font-sans); font-weight: 600; font-size: 15px;
  line-height: var(--leading); color: var(--osk-accent-text);
  font-variant-numeric: tabular-nums; margin: 0; text-box: trim-both cap alphabetic; }
.f-title { font-family: var(--osk-font-sans); font-weight: 600;
  font-size: var(--osk-web-h3); line-height: var(--leading);
  letter-spacing: var(--osk-track-tight); color: var(--osk-ink);
  margin: 0; text-box: trim-both cap alphabetic; }
.f-sub { display: block; font-size: 13.5px; letter-spacing: 0; font-weight: 400;
  color: var(--osk-muted); margin-top: var(--osk-space-4); }
.f-copy { font-size: 15.5px; line-height: var(--leading); margin: 0;
  color: var(--osk-body); max-width: 52ch; text-box: trim-both cap alphabetic; }

/* — imagery split: the photograph is a grid object, blended, swappable — */
.split { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: var(--leading) clamp(24px, 5vw, 96px); align-items: center;
  padding: calc(2 * var(--leading)) 0 calc(3 * var(--leading)); }
.split-title { font-family: var(--osk-font-sans); font-weight: 600;
  font-size: var(--osk-web-h2); line-height: calc(1.5 * var(--leading));
  letter-spacing: var(--osk-track-tight); color: var(--osk-ink);
  margin: 0; text-box: trim-both cap alphabetic; }
.split-copy .note { font-size: 15.5px; line-height: var(--leading);
  color: var(--osk-body); margin: calc(var(--leading) - 1cap) 0 0;
  max-width: 48ch; text-box: trim-both cap alphabetic; }
.split-figure { margin: 0; }
/* the bundled photograph's natural ratio pins the box, so a swapped image
   cover-crops into the same frame */
.split-figure image-slot { width: 100%; aspect-ratio: 1600 / 1261; }

/* — product panel mock (surfaces, borders and radii: theme.css) — */
.shots { padding: 0 0 calc(3 * var(--leading)); }
.shots .note { font-size: 15.5px; line-height: var(--leading); color: var(--osk-body);
  margin: calc(var(--leading) - 1cap) 0 0; max-width: 52ch; text-box: trim-both cap alphabetic; }
.panel { margin-top: calc(1.5 * var(--leading)); overflow: hidden; }
.panel-bar { display: flex; align-items: center; gap: var(--osk-space-6);
  padding: var(--osk-space-5) var(--osk-space-8); border-bottom: var(--osk-rule-section-b);
  font-size: 12.5px; }
.panel-dots { display: flex; gap: var(--osk-space-3); }
.panel-dots span { width: 8px; height: 8px; border-radius: var(--osk-radius-pill); }
.panel-body { display: grid; grid-template-columns: 200px 1fr; }
.panel-side { border-right: var(--osk-rule-section-b); padding: var(--osk-space-9) 0;
  display: flex; flex-direction: column; gap: var(--osk-space-1); }
.panel-side a { font-size: 13.5px; color: var(--osk-muted);
  padding: var(--osk-space-4) var(--osk-space-9); text-decoration: none;
  border-left: 2px solid transparent; transition: var(--osk-transition); }
.panel-main { padding: var(--osk-space-10) 28px 28px; display: flex; flex-direction: column; gap: var(--osk-space-9); }
.panel-title { font: var(--osk-type-h3); margin: 0; }
.tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--osk-space-6); min-width: 0; }
.tile { min-width: 0; padding: var(--osk-space-7) var(--osk-space-8); }
.tile b { display: block; font: var(--osk-type-stat); font-variant-numeric: tabular-nums; }
.tile span { display: block; font: var(--osk-type-legend); text-transform: uppercase; margin-top: var(--osk-space-3); }
.bars { display: flex; align-items: flex-end; gap: var(--osk-space-5); height: 110px; }
.bars i { flex: 1; border-radius: 2px 2px 0 0; }
.rows { display: flex; flex-direction: column; }
.rows div { display: flex; justify-content: space-between; gap: var(--osk-space-8);
  font-size: 13.5px; padding: 9px 0; border-top: var(--osk-rule-1);
  font-variant-numeric: tabular-nums; }
.panel-caption { font-size: 13px; line-height: var(--leading); color: var(--osk-muted); margin: var(--half) 0 0; }
@media (max-width: 720px) {
  .panel-body { grid-template-columns: 1fr; }
  .panel-side { flex-direction: row; overflow-x: auto; border-right: 0;
    border-bottom: var(--osk-rule-section-b); padding: var(--osk-space-4) var(--osk-space-6); }
  .panel-side a { border-left: 0; white-space: nowrap; }
  .tiles { grid-template-columns: 1fr; }
}

/* — rotating hero panel — */
/* the four hub tabs hold one row — a wrapped second line reads as an
   overflow fault on a panel this small */
.panel-tabs { display: flex; gap: var(--osk-space-1); padding: var(--osk-space-4) var(--osk-space-5);
  border-bottom: var(--osk-rule-section-b); }
.panel-tabs button { white-space: nowrap; min-width: 0; }
.panel-tabs button { font: var(--osk-type-row-meta); font-family: var(--osk-font-sans);
  padding: var(--osk-space-2) var(--osk-space-4); background: none; border: 0; cursor: pointer; }
.panel-stage { display: grid; }
.panel-stage .pv { grid-area: 1 / 1; opacity: 0; transition: opacity 450ms var(--osk-ease); pointer-events: none; }
.panel-stage .pv.on { opacity: 1; pointer-events: auto; }
@media (prefers-reduced-motion: reduce) { .panel-stage .pv { transition: none; } }

/* — split hero — */
.hero-b { display: grid; grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  gap: var(--leading) clamp(24px, 4vw, 72px); align-items: center;
  padding: calc(3 * var(--leading)) 0; }
.hero-b .display { font-size: clamp(36px, 4.4vw, 62px); line-height: clamp(41px, 4.9vw, 69px); }
.hero-b .panel { margin-top: 0; }
@media (max-width: 880px) { .hero-b { grid-template-columns: 1fr; } }

/* — inline hero stats (variant C) — */
.hero-stats { display: flex; flex-wrap: wrap; gap: var(--leading) calc(2.5 * var(--leading));
  margin-top: calc(2 * var(--leading)); }
.hero-stats .stat-num { font-size: 30px; line-height: var(--leading); }

/* — product cards: the one equal-card grid the web layout allows — */
.prods { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--leading); margin-top: calc(1.5 * var(--leading)); }
@media (max-width: 720px) { .prods { grid-template-columns: 1fr; } }

/* — contact — */
.contact-grid { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: calc(2 * var(--leading)) clamp(24px, 5vw, 96px);
  padding: calc(1.5 * var(--leading)) 0 calc(3 * var(--leading)); align-items: start; }
.form { display: flex; flex-direction: column; gap: var(--leading); max-width: 560px; }
.form .field { display: flex; flex-direction: column; gap: var(--osk-space-3); }
.form label { text-transform: uppercase; }
.steps { display: flex; flex-direction: column; gap: var(--leading); }
.step { display: grid; grid-template-columns: 40px 1fr; gap: var(--osk-space-8); align-items: baseline; }
.step .f-num { font-size: 14px; }
.step p { margin: 0; font-size: 15px; line-height: var(--leading); color: var(--osk-body); }
@media (max-width: 880px) { .contact-grid { grid-template-columns: 1fr; } }

/* — quote: hanging punctuation, measured for Inter — */
.quote { padding: calc(2.5 * var(--leading)) 0 calc(3.5 * var(--leading)); }
.quote blockquote { font-family: var(--osk-font-sans); font-weight: 600;
  font-size: clamp(24px, 2.6vw, 34px); line-height: calc(1.5 * var(--leading));
  letter-spacing: var(--osk-track-tight); color: var(--osk-ink);
  max-width: 32ch; margin: 0; text-indent: -0.474em; text-box: trim-both cap alphabetic; }
.quote figcaption { font-size: 15.5px; line-height: var(--leading); color: var(--osk-muted);
  margin: calc(2 * var(--leading) - 1cap) 0 0; text-indent: -1.267em;
  text-box: trim-both cap alphabetic; }
@media (max-width: 720px) { .quote blockquote, .quote figcaption { text-indent: 0; } }

/* — close / signup — */
.close { padding: calc(2.5 * var(--leading)) 0 calc(2 * var(--leading)); }
.close h3 { font-family: var(--osk-font-sans); font-weight: 600; font-size: var(--osk-web-h3);
  line-height: var(--leading); color: var(--osk-ink); margin: 0; text-box: trim-both cap alphabetic; }
.close .sub { font-size: 15.5px; line-height: var(--leading); color: var(--osk-body);
  margin: calc(var(--leading) - 1cap) 0 0; max-width: var(--measure); text-box: trim-both cap alphabetic; }
.signup { display: flex; gap: var(--osk-space-6); align-items: stretch; max-width: 480px; margin-top: var(--leading); }
.signup .input { flex: 1; }
.signup .input, .signup .btn { min-height: 40px; }
footer { padding: calc(2 * var(--leading)) 0; font-size: 13px; line-height: var(--leading);
  color: var(--osk-muted); }

/* — responsive collapse — */
@media (max-width: 1000px) {
  .feature { grid-template-columns: 1fr; gap: var(--osk-space-4); }
  .f-copy { max-width: var(--measure); margin-top: var(--osk-space-5); }
}
@media (max-width: 720px) {
  .hero { padding-top: calc(2.5 * var(--leading)); }
  .stats .grid { grid-template-columns: repeat(2, 1fr); justify-content: start; }
  .split { grid-template-columns: 1fr; }
  .split-figure { order: -1; }
}


/* ── app screens inside the hero panel ────────────────────────────────────
   Not a generic dashboard mock: this is the K3ystone grammar at web scale —
   a framed hero panel with ONE hero number and a SegBar, section headers
   carrying counts, triage cards whose 3px left edge means "late or waiting
   on you", and rows whose facts are separated by the middot. */
.app { display: flex; flex-direction: column; gap: var(--osk-space-5);
  padding: var(--osk-space-7) var(--osk-space-8) var(--osk-space-9); min-height: 452px; }
.app-hero { position: relative; overflow: hidden;
  background: var(--osk-page); border: var(--osk-rule-section-b);
  border-radius: var(--osk-radius-lg); padding: var(--osk-space-7) var(--osk-space-8); }
.app-hero::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 3px;
  background: var(--osk-gradient); }
.app-kicker { margin: 0; font: var(--osk-type-kicker); font-weight: 600;
  letter-spacing: var(--osk-track-kicker); text-transform: uppercase;
  color: var(--osk-accent-text); }
.app-hero-top { display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--osk-space-6); margin-top: var(--osk-space-4); }
.app-hero-top h4 { margin: 0; font: var(--osk-type-h3); color: var(--osk-ink); }
.app-num { font-family: var(--osk-font-sans); font-weight: 600; font-size: 34px; line-height: 1.05;
  color: var(--osk-ink); font-variant-numeric: tabular-nums; letter-spacing: var(--osk-track-tight); }
.app-cap { margin: var(--osk-space-2) 0 0; font: var(--osk-type-row-meta); color: var(--osk-muted); }
/* the caption's second fact is only coloured when it MEANS something —
   semantic colour is never decoration */
.app-cap em { font-style: normal; color: var(--osk-body); }
.app-cap em[data-tone="danger"] { color: var(--osk-danger); }
.app-cap em[data-tone="warning"] { color: var(--osk-warning); }
.segbar { display: flex; gap: 2px; height: 8px; margin-top: var(--osk-space-6); }
.segbar i:first-child { border-radius: var(--osk-radius-pill) 2px 2px var(--osk-radius-pill); }
.segbar i:last-child { border-radius: 2px var(--osk-radius-pill) var(--osk-radius-pill) 2px; }
.seg-legend { display: flex; flex-wrap: wrap; gap: var(--osk-space-4) var(--osk-space-7);
  margin-top: var(--osk-space-5); font: var(--osk-type-legend); color: var(--osk-muted); }
.seg-legend span { display: inline-flex; align-items: center; gap: var(--osk-space-3); }
.seg-legend i { width: 6px; height: 6px; border-radius: var(--osk-radius-pill); }
.seg-legend b { color: var(--osk-body); font-weight: 600; font-variant-numeric: tabular-nums; }
.app-sec { display: flex; justify-content: space-between; align-items: baseline;
  margin: var(--osk-space-3) 0 0; padding-top: var(--osk-space-5);
  border-top: var(--osk-rule-1);
  font: var(--osk-type-section); font-weight: 600; letter-spacing: var(--osk-track-section);
  text-transform: uppercase; color: var(--osk-muted); }
.app-sec b { color: var(--osk-faint); font-variant-numeric: tabular-nums; }
.triage { display: flex; align-items: center; justify-content: space-between;
  gap: var(--osk-space-6); padding: var(--osk-space-5) var(--osk-space-7);
  background: var(--osk-page); border: var(--osk-rule-1);
  border-left: 3px solid var(--osk-rule-section);
  border-radius: var(--osk-radius); box-shadow: var(--osk-shadow-sm); }
.triage[data-tone="danger"] { border-left-color: var(--osk-danger); }
.triage[data-tone="warning"] { border-left-color: var(--osk-warning); }
.t-title { margin: 0; font: var(--osk-type-row-title); color: var(--osk-ink); }
.t-meta { margin: 2px 0 0; font: var(--osk-type-row-meta); color: var(--osk-muted); }
.t-right { flex: none; font-family: var(--osk-font-sans); font-weight: 600; font-size: 12.5px;
  color: var(--osk-body); white-space: nowrap; font-variant-numeric: tabular-nums; }
.t-action { padding: 5px var(--osk-space-5); border-radius: var(--osk-radius-pill);
  background: var(--osk-accent-soft); color: var(--osk-accent-text);
  font-size: 11px; letter-spacing: var(--osk-track-section); text-transform: uppercase; }
.approws { display: flex; flex-direction: column; }
.approw { display: grid; grid-template-columns: 8px minmax(0, 1fr) auto;
  gap: var(--osk-space-6); align-items: center; padding: 9px 0; border-top: var(--osk-rule-1); }
.approw .dot { width: 8px; height: 8px; border-radius: var(--osk-radius-pill); }

/* ── product cards: the flagship leads, the other three follow ──────────
   K3ystone is live and is the platform's front door, so it takes a full-width
   lead card; the remaining three sit three-up beneath it. Status is a word,
   never a colour alone. */
.prods { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.prods > .card { grid-column: span 2; }
.prods > .card-lead { grid-column: span 6;
  display: grid; grid-template-columns: 56px minmax(0, 5fr) minmax(0, 6fr);
  gap: var(--osk-space-6) clamp(20px, 3vw, 40px); align-items: start; }
.card-lead .lead-head { grid-column: 2; }
.card-lead .lead-body { grid-column: 3; display: flex; flex-direction: column;
  gap: var(--osk-space-6); }
.card-lead img { grid-row: span 2; }
.card-facts { display: flex; flex-wrap: wrap; gap: var(--osk-space-3) var(--osk-space-5);
  font: var(--osk-type-row-meta); color: var(--osk-muted); }
.card-facts span { display: inline-flex; align-items: center; gap: var(--osk-space-5); }
.card-facts span + span::before { content: "·"; color: var(--osk-faint); }
.card-head { display: flex; align-items: center; justify-content: space-between;
  gap: var(--osk-space-6); }
.tag-state { flex: none; padding: 4px var(--osk-space-4); border-radius: var(--osk-radius-sm);
  font: var(--osk-type-tag); font-weight: 600; letter-spacing: var(--osk-track-section);
  text-transform: uppercase; background: var(--osk-neutral-fill); color: var(--osk-muted); }
.tag-state[data-live] { background: var(--osk-accent-soft); color: var(--osk-accent-text); }
@media (max-width: 900px) {
  .prods { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .prods > .card { grid-column: span 1; }
  .prods > .card-lead { grid-column: span 2; grid-template-columns: 56px minmax(0, 1fr); }
  .card-lead .lead-body { grid-column: 2; }
  .card-lead img { grid-row: auto; }
}
@media (max-width: 620px) {
  .prods, .prods > .card-lead { grid-template-columns: 1fr; }
  .prods > .card, .prods > .card-lead { grid-column: span 1; }
  .card-lead .lead-head, .card-lead .lead-body { grid-column: 1; }
}

/* ── The K3Y programme strip (home page) ─────────────────────────────────
   The shop window for programmes.html: four equal tiles, no flagship, read
   left to right by altitude — person, leader, team, floor. Deliberately
   lighter than the product cards above it. Software is what OSk3y sells; the
   programmes are what the platform carries. */
.k3y-strip { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--osk-space-8); margin-top: calc(1.5 * var(--leading)); }
@media (max-width: 900px) { .k3y-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .k3y-strip { grid-template-columns: 1fr; } }
.k3y-strip a { position: relative; overflow: hidden; display: block;
  padding: var(--osk-space-8); text-decoration: none; color: inherit;
  background: var(--osk-surface); border: var(--osk-rule-section-b);
  border-radius: var(--osk-radius);
  transition: var(--osk-transition), transform var(--osk-duration) var(--osk-ease); }
.k3y-strip a:hover { border-color: var(--osk-accent); transform: translateY(-1px); }
.k3y-strip a::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 3px;
  background: var(--tint); }
.k3y-strip .code { display: inline-flex; font: var(--osk-type-tag); font-weight: 600;
  letter-spacing: var(--osk-track-section); text-transform: uppercase;
  padding: 4px var(--osk-space-4); border-radius: var(--osk-radius-sm);
  background: var(--tint-soft); color: var(--tint); }
.k3y-strip h3 { margin: var(--osk-space-6) 0 0; font-family: var(--osk-font-sans);
  font-weight: 600; font-size: 17px; line-height: 23px; color: var(--osk-ink); }
.k3y-strip p { margin: var(--osk-space-3) 0 0; font-size: 13.5px; line-height: 20px;
  color: var(--osk-muted); }

/* ── stat band: hairline-parted columns, the numbers carrying the section ── */
.stats .band-label { margin: 0 0 calc(1.5 * var(--leading));
  font: var(--osk-type-section); font-weight: 600; letter-spacing: var(--osk-track-section);
  text-transform: uppercase; color: #8fb3ff; }
.stats .grid { grid-template-columns: repeat(4, minmax(0, 1fr)); justify-content: stretch; }
.stats .grid > div { padding-left: clamp(16px, 2.4vw, 32px);
  border-left: 1px solid rgba(126, 164, 255, 0.22); }
.stats .grid > div:first-child { padding-left: 0; border-left: 0; }
.stats .stat-num { font-size: clamp(38px, 4.2vw, 60px); }
@media (max-width: 720px) {
  /* Re-assert the two-up stack. The unconditional `repeat(4, …)` above lands
     later in the cascade than the ≤720px rule further up the file, so without
     this the strip stayed 4 columns on a phone: ~66px cells, clipped stat
     numbers, and 34px of horizontal page overflow under the sticky nav. The
     nth-child(odd) reset below already assumed two columns. */
  .stats .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stats .grid > div:nth-child(odd) { padding-left: 0; border-left: 0; }
}


/* ── engagement timeline ──────────────────────────────────────────────────
   Not an illustration — a diagram in the system's own viz grammar: the
   sequence palette carries the four stages (categories, never health), the
   axis is the 10px axis role, and the release marker is the one dashed line
   on the page. */
.timeline { background: var(--osk-surface); border: var(--osk-rule-card);
  border-radius: var(--osk-radius-lg); box-shadow: var(--osk-shadow-lg);
  padding: var(--osk-space-9) 28px var(--osk-space-9); }
.tl-head { display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--osk-space-8); padding-bottom: var(--osk-space-7);
  border-bottom: var(--osk-rule-section-b); }
.tl-kicker { margin: 0; font: var(--osk-type-kicker); font-weight: 600;
  letter-spacing: var(--osk-track-kicker); text-transform: uppercase;
  color: var(--osk-accent-text); }
.tl-note { margin: 0; font: var(--osk-type-row-meta); color: var(--osk-muted); }
.tl-grid { position: relative; padding-top: var(--osk-space-7); }
.tl-axis { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr));
  margin-left: 42%; font: var(--osk-type-legend); color: var(--osk-faint);
  font-variant-numeric: tabular-nums; padding-bottom: var(--osk-space-5); }
.tl-axis span { text-align: center; }
.tl-axis span:first-child { text-align: left; }
.tl-track { display: grid; grid-template-columns: 42% minmax(0, 1fr);
  align-items: center; gap: var(--osk-space-6); padding: var(--osk-space-5) 0;
  border-top: var(--osk-rule-1); }
.tl-label { margin: 0; font: var(--osk-type-row-title); color: var(--osk-ink);
  padding-right: var(--osk-space-6); }
.tl-label span { display: block; font: var(--osk-type-row-meta); color: var(--osk-muted);
  margin-top: 2px; }
.tl-lane { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr));
  height: 10px; background: var(--osk-bar-mid);
  border-radius: var(--osk-radius-pill); }
.tl-lane i { height: 10px; border-radius: var(--osk-radius-pill); }
/* the release marker: the line hangs from under the axis, its label reads
   back to the left so it never runs past the panel edge */
.tl-marker { position: absolute; top: 26px; bottom: var(--osk-space-5);
  left: calc(42% + (100% - 42%) * 0.625);
  border-left: 1px dashed var(--osk-border); pointer-events: none; }
.tl-marker span { position: absolute; top: -22px; right: var(--osk-space-4);
  font: var(--osk-type-legend); color: var(--osk-accent-text); white-space: nowrap; }
.tl-foot { display: flex; flex-wrap: wrap; gap: var(--osk-space-4) var(--osk-space-9);
  margin-top: var(--osk-space-8); padding-top: var(--osk-space-7);
  border-top: var(--osk-rule-section-b);
  font: var(--osk-type-row-meta); color: var(--osk-muted); }
.tl-foot b { color: var(--osk-body); font-weight: 600; }
@media (max-width: 620px) {
  .tl-axis { margin-left: 0; }
  .tl-track { grid-template-columns: 1fr; gap: var(--osk-space-4); }
  .tl-marker { display: none; }
}


/* ── the briefing screen (TurnK3y Today) ──────────────────────────────────
   The real screen has no hero number: it opens with a sentence derived from
   what is true, then the leave year as a bar. Lead clause in ink, the read
   in body ink. */
.app-brief { margin: var(--osk-space-5) 0 0; font-family: var(--osk-font-sans);
  font-size: 16px; line-height: 1.45; color: var(--osk-body); }
.app-brief b { color: var(--osk-ink); font-weight: 600; }
.insight { display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--osk-space-8); align-items: center;
  padding: var(--osk-space-7); background: var(--osk-page);
  border: var(--osk-rule-1); border-radius: var(--osk-radius); }
.i-kicker { margin: 0; font: var(--osk-type-kicker); font-weight: 600;
  letter-spacing: var(--osk-track-kicker); text-transform: uppercase;
  color: var(--osk-accent-text); }
.i-copy { margin: var(--osk-space-3) 0 0; font: var(--osk-type-row-meta); color: var(--osk-muted); }
.i-value { margin: 0; text-align: right; font-family: var(--osk-font-sans); font-weight: 600;
  font-size: 28px; line-height: 1.05; color: var(--osk-ink);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.i-value span { display: block; margin-top: var(--osk-space-3);
  font: var(--osk-type-legend); font-weight: 600; letter-spacing: var(--osk-track-section);
  text-transform: uppercase; color: var(--osk-accent-text); }

/* — Shift demo films — */
.film { margin-top: calc(1.5 * var(--leading)); }
.film-title { margin: var(--osk-space-4) 0; }
.film-copy { max-width: 62ch; }
.film-pair { display: grid; grid-template-columns: 1fr; gap: var(--leading);
  margin-top: calc(1.5 * var(--leading)); }
@media (min-width: 860px) { .film-pair { grid-template-columns: 1fr 1fr; } }
.film-item { margin: 0; display: flex; flex-direction: column;
  gap: var(--osk-space-5); }
.film-frame { position: relative; display: block; width: 100%; padding: 0;
  background: var(--osk-surface); border: var(--osk-rule-card);
  border-radius: var(--osk-radius-lg); box-shadow: var(--osk-shadow-lg);
  overflow: hidden; cursor: pointer;
  transition: border-color var(--osk-duration) var(--osk-ease),
              transform var(--osk-duration) var(--osk-ease); }
.film-frame:hover { transform: translateY(-2px); border-color: var(--osk-accent); }
.film-frame:focus-visible { outline: 2px solid var(--osk-accent-text);
  outline-offset: 3px; }
.film-frame img, .film-item video { display: block; width: 100%; height: auto; }
.film-item video { border-radius: var(--osk-radius-lg); }
/* No full-frame scrim: it smudges the light poster. The button carries its
   own separation instead, so it reads on either background. */
.film-play { position: absolute; inset: 0; margin: auto; z-index: 1;
  width: 64px; height: 64px; border-radius: var(--osk-radius-pill);
  background: rgba(12, 20, 40, .70); border: 1px solid rgba(255, 255, 255, .38);
  backdrop-filter: blur(6px);
  box-shadow: 0 4px 18px rgba(0, 0, 0, .45); }
.film-play::after { content: ""; position: absolute; top: 50%; left: 54%;
  transform: translate(-50%, -50%); border-style: solid;
  border-width: 11px 0 11px 18px;
  border-color: transparent transparent transparent #fff; }
.film-cap { font: var(--osk-type-row-meta); color: var(--osk-muted); }
.film-cap strong { color: var(--osk-ink); font-weight: 600; }
.film-cap span { display: block; margin-top: var(--osk-space-2);
  color: var(--osk-faint); }
@media (prefers-reduced-motion: reduce) { .film-frame { transition: none; } }
/* — Clients pill: the client-document door, beside (not instead of) Sign in.
   Sign in is the platform account (Supabase, per person, four hubs); this is
   the shared client credential that opens programme documents. Two doors
   because they are two systems — see netlify/lib/client-session.ts. — */
.nav-pill { display: inline-flex; align-items: center; gap: var(--osk-space-4);
  height: 36px; padding: 0 15px; border-radius: var(--osk-radius-pill);
  border: 1px solid var(--osk-rule-section); background: var(--osk-surface-2);
  color: var(--osk-ink); font-size: 14px; font-weight: 500; white-space: nowrap;
  transition: var(--osk-transition); }
.nav-pill:hover { border-color: var(--osk-border); color: var(--osk-ink); }
.nav-pill-dot { width: 6px; height: 6px; border-radius: var(--osk-radius-pill);
  background: var(--osk-shift); flex: none; }
/* the nav's own rule keeps links at body colour; the pill carries ink instead */
.nav a.nav-pill:not(.btn) { color: var(--osk-ink); }
/* below 480px the section links fold away — the pill keeps its place and grows
   to the 44px hit floor, as Sign in already does */
@media (max-width: 480px) {
  .nav > a.nav-pill { display: inline-flex; min-height: var(--osk-hit); height: auto; }
}
