/* ============================================================
   kordarna.com, the public site
   The tokens are the app's own (prototype :root / .dark, and CLAUDE.md's design system).
   Kept as a plain stylesheet on purpose: this site is static, fast and crawlable, which
   is the opposite of what the app is, and nothing here should import from app/.
   ============================================================ */

:root {
  --bg: #ffffff;
  --bg-soft: #f7f7f5;
  --bg-card: #ffffff;
  --text: #1d1c1a;
  --text-2: #73726e;
  --text-3: #a5a4a0;
  --border: #e9e9e7;
  --shadow: 0 1px 2px rgba(15, 15, 15, 0.04), 0 4px 14px rgba(15, 15, 15, 0.05);
  --shadow-lg: 0 4px 12px rgba(15, 15, 15, 0.08), 0 20px 50px rgba(15, 15, 15, 0.16);
  --grad-brand: linear-gradient(135deg, #ff5e62 0%, #b44ae0 55%, #6e6bf5 100%);

  --font: ui-sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
  --mono: ui-monospace, 'SF Mono', 'Cascadia Mono', 'Courier New', monospace;

  --wrap: 1080px;
  --gutter: 24px;
  /* 44px of bar plus its 1px bottom border. Named because the dark hero has to
     pull itself up by exactly this much to sit underneath it. */
  --nav-h: 45px;
}

/* LIGHT ONLY, owner's call, 2026-08-27. The app follows the reader's theme
   because people write in it at night; a marketing site is read once, in
   daylight, and one set of colours is one set of colours to get right. Every
   value above is therefore stated absolutely: there is no dark block to fall
   through to, and `color-scheme` stops the browser tinting form controls dark
   underneath us on a device set to dark. */
:root { color-scheme: light; }

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

/* A HEADING USED AS AN ANCHOR HAS TO CLEAR THE STICKY BAR.
   The page sections get away without this because each carries 82px of its own
   top padding, so their headings land well below the header. A bare heading has
   none: /support.html#faq landed the "Common questions" line EXACTLY underneath
   the 44px bar, so following the footer's FAQ link looked like a page that had
   not moved at all. Scoped to headings rather than to every `[id]`, because the
   sections already land correctly and adding margin to them would only open a
   gap above something that was fine. */
h2[id], h3[id] { scroll-margin-top: 64px; }

body {
  margin: 0;
  font-family: var(--font);
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  line-height: 1.6;
}

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

a { color: inherit; }

/* ---------------------------------------------------------------- type */

h1, h2, h3 { letter-spacing: -0.03em; line-height: 1.12; margin: 0; }
h1 { font-size: clamp(38px, 6.2vw, 66px); font-weight: 680; }
h2 { font-size: clamp(27px, 3.6vw, 38px); font-weight: 670; }
h3 { font-size: 17px; font-weight: 640; letter-spacing: -0.015em; }

p { margin: 0; color: var(--text-2); }

.lede { font-size: clamp(16px, 1.9vw, 19px); color: var(--text-2); max-width: 54ch; }

/* ---------------------------------------------------------------- chrome */

/* ---------------------------------------------------------------- header

   LOW PROFILE, after Apple's global nav (owner's note, 10 September 2026:
   "a bit lower profile, take inspiration from Apple's website").

   The four traits worth borrowing, and they are the ones that make that bar
   read as chrome rather than as content:
     * it is THIN — 44px, not 62. The bar should be the smallest thing on the
       page, because it is the only thing on every page.
     * the type is SMALL — 12px. Nav labels are signposts, not prose, and at
       13.5px they were competing with the copy underneath them.
     * it is TRANSLUCENT and heavily blurred, so the page reads as passing
       BEHIND it rather than stopping at it.
     * the items are SPREAD, not bunched at the right. Even spacing across the
       bar is the most recognisable part of the look and it costs nothing.

   What is deliberately NOT borrowed: Apple's dark bar, and its full-width
   flyout menus. This site is light-only by the owner's call, and five links do
   not need a mega-menu. */
/* `body > header`, NOT `header`. A bare element selector here was a trap with a
   five-day fuse: the release notes page gives every release its own
   <article class="release-note"><header> (correct HTML, a heading block for a
   section), and those inherited the whole bar, so each version number pinned
   itself to the top of the window and painted its own blurred strip straight
   over the navigation. The site's own bar is always a direct child of body, on
   every page, so the child combinator says exactly what is meant. Anything that
   should look like the bar asks for it by class. */
body > header {
  position: sticky; top: 0; z-index: 20;
  /* Thinner AND more transparent than before: at 44px the bar is small enough
     that a near-opaque ground would read as a hard shelf across the page. */
  background: color-mix(in srgb, var(--bg) 72%, transparent);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid transparent;
  transition: border-color .2s, background .3s, color .3s;
}
header.stuck { border-bottom-color: var(--border); }

/* ---- THE BAR OVER THE DARK HERO (10 September 2026) ----

   THREE STATES, because the bar passes over three different things.

   `position: sticky` keeps an element in normal flow, so the header was taking
   its own 45px of space ABOVE the band — and since the glow starts where the band
   starts, the top 45px of the page was a flat dark strip with the glow cut off
   square beneath it. That seam is what the owner saw. The band is now pulled up
   underneath the bar (see `.hero` below) so the glow runs to the very top of the
   page, and the bar sits ON it.

   1. AT REST the bar is fully transparent: no ground, no blur, nothing but the
      links. This is the state the owner asked for and the one anybody arriving
      at the page sees first.
   2. ONCE SCROLLING it takes a dark translucent ground. This is not decoration:
      the product shot is a bright white card that passes directly under the bar
      for six hundred pixels of the band, and white links crossing it disappear
      completely. A bar with a ground of its own stays readable over anything,
      which is what Apple's dark nav does and why it does it.
   3. PAST THE BAND it becomes the ordinary light bar, dark links and all.

   `body.hero-dark` rather than a rule on `.hero`, because the header is a SIBLING
   of the hero, not a child — it cannot ask what it is currently over. */
body.hero-dark header:not(.stuck) {
  background: color-mix(in srgb, #191919 72%, transparent);
  border-bottom-color: transparent;
}
/* State 1. `background: none` AND the blur off: a backdrop-filter with nothing
   over it still frosts what is behind, which on a glow reads as a smeared band
   exactly where the bar is — the same seam by another route. */
body.hero-dark header:not(.scrolled) {
  background: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
/* THE WORDMARK IS AN <img>, SO `color` DOES NOTHING TO IT. img/wordmark.svg
   carries a hard-coded `fill="#000000"` and is loaded as an image, not inlined,
   so it has no access to this document's currentColor — it drew pure black on
   the dark bar and the mark simply vanished. (The base `header .wordmark { color }`
   rule above has always been inert for the same reason; it only ever looked
   right because black on a white bar is what was wanted anyway.)
   `brightness(0)` flattens every pixel to black while keeping its alpha, and
   `invert(1)` then makes it white — which is correct whatever colour a future
   export of the artwork happens to use. An inline <svg> would be the other fix,
   and a bigger change to four pages for no visible gain. */
body.hero-dark header:not(.stuck) .wordmark { filter: brightness(0) invert(1); }
body.hero-dark header:not(.stuck) svg { color: #e8e8e6; }
body.hero-dark header:not(.stuck) nav a { color: #9c9b97; }
body.hero-dark header:not(.stuck) nav a:hover { color: #ffffff; }
body.hero-dark header:not(.stuck) nav a[aria-current='page'],
body.hero-dark header:not(.stuck) .nav-app { color: #ffffff; }
header .wrap { display: flex; align-items: center; gap: 28px; height: 44px; }
/* 15px, down from 19: the wordmark sets the bar's whole weight, and a mark
   sized for a 62px bar looks planted in a 44px one. */
header svg, header .wordmark { height: 15px; width: auto; color: var(--text); display: block; }

/* `align-items: center` is load-bearing, not tidiness. The default is stretch,
   which was invisible while every child was plain text of the same height; the
   moment one item had padding it became the tallest and stretched the others to
   match — and a stretched anchor draws its text at the TOP of the box, so the
   links floated above the others' centred labels. Kept even though the pill is
   gone, because the next person to add a padded item will not know. */
header nav {
  display: flex; align-items: center;
  /* `flex: 1` plus `space-between` is the Apple spread: the links take the whole
     bar between the wordmark and the right edge and share it evenly, rather than
     huddling against one side. `max-width` stops them drifting absurdly far apart
     on a very wide screen, where five items across 1080px would read as five
     unrelated words. */
  flex: 1; justify-content: space-between; max-width: 660px; margin-left: auto;
}
header nav a {
  font-size: 12px; color: var(--text-2); text-decoration: none;
  transition: color 0.15s; white-space: nowrap;
}
header nav a:hover { color: var(--text); }
/* The page you are on, named quietly. Apple does this with weight, not a rule
   under the word, which keeps the bar's line unbroken. */
header nav a[aria-current='page'] { color: var(--text); font-weight: 600; }

@media (max-width: 900px) {
  /* Below this the five labels stop fitting side by side with room to breathe,
     so they close up and sit right rather than stretching. */
  header nav { flex: none; justify-content: flex-end; gap: 20px; max-width: none; }
}
/* BELOW 720 THE LINKS GO AND THE CTA STAYS (owner, 12 Sep 2026). The whole nav
   used to vanish here, which left a phone with no way into the app from the bar
   at all — and, since the closing section was removed, no way in from the bottom
   of the page either.

   This IS the pill the note further down argues against, and the argument does
   not apply here. It was about a padded button sitting among five text links,
   where it set the bar's minimum height and drew a hard edge across an open
   strip. At this width there are no links left: the bar holds a wordmark and
   this, so the pill is the only shape in it rather than the loud one among
   several.

   30px inside a 45px bar, so it changes no height and `--nav-h` still describes
   the bar the hero pulls itself up under. The brand gradient reads on both
   grounds — transparent over the dark hero and solid once scrolled — which is
   the property that makes it the CTA everywhere else on the page. */
@media (max-width: 720px) {
  header nav { flex: none; justify-content: flex-end; gap: 0; max-width: none; }
  header nav a:not(.nav-app) { display: none; }
  header nav .nav-app {
    display: inline-flex; align-items: center;
    height: 30px; padding: 0 15px; border-radius: 999px;
    background: var(--grad-brand); color: #fff; font-size: 12.5px;
    box-shadow: 0 4px 12px rgba(180, 74, 224, 0.26);
  }
  /* The dark-hero override paints the label white, which it already is. Stated
     so a future change to that rule cannot quietly turn it dark on a gradient. */
  body.hero-dark header:not(.stuck) .nav-app { color: #fff; }
}

/* ---------------------------------------------------------------- buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 42px; padding: 0 24px; border-radius: 999px;
  font-size: 14px; font-weight: 600; text-decoration: none; border: 0; cursor: pointer;
  font-family: inherit; white-space: nowrap;
}
.btn-grad { background: var(--grad-brand); color: #fff; box-shadow: 0 6px 18px rgba(180, 74, 224, 0.28); }
.btn-grad:hover { filter: brightness(1.05); }
.btn-out { background: transparent; color: var(--text); border: 1px solid var(--border); }
.btn-out:hover { background: var(--bg-soft); }

/* ---------------------------------------------------------------- hero */

/* ---------------------------------------------------------------- the hero

   DARK, WITH THE APP'S OWN AMBIENT GLOW BEHIND IT (owner, 10 September 2026:
   "make the top section of the home page dark with a background gradient
   similar to the ideas area and new project pop-up from the app").

   This is a deliberate exception to the site being light-only (27 Aug 2026),
   not a reversal of it: one band at the top, the rest of the page unchanged.
   The point is recognition — somebody who has seen the Ideas page should meet
   the same surface here before they ever sign in.

   The glow is PORTED, not approximated: the shapes, the sizes, the masks and
   the keyframes below are app/src/components/ambientGlow.css, with the accent
   variables resolved to the brand's own three stops because this site has no
   accent setting to follow. Keeping the numbers identical is the whole point;
   if that file is ever retuned, retune this with it.

   Everything is transform-only on compositor layers: no blur filter and no
   repaint per frame, which matters more here than in the app because this is
   the first thing a visitor's browser has to paint. */
/* PULLED UP UNDER THE BAR, and padded back down by the same amount, so the glow
   runs to the very top of the page while the headline sits exactly where it did.
   This is the "sit on top of the page and adjust the content to compensate" half
   of the owner's note; the transparent bar above is the other half. Only on this
   page: every other page keeps the header in normal flow where it belongs. */
body.hero-dark .hero { margin-top: calc(var(--nav-h) * -1); }
/* TWO dark bands on this page since 11 Sep 2026: the hero and the privacy section,
   which the owner asked to carry "the same gradient background as section 1". One
   selector list rather than two copies of the ground, because the whole point of the
   request is that they match — and a second copy is what stops matching first. Both
   also need `position`/`overflow`/`isolation` for the drifting glow, and both are
   centred, so the block really is shared rather than coincidentally similar. */
/* THE DARK PALETTE LIVES ON :root, not on the two sections that first used it.
   A custom property is only visible to an element and its descendants, so while
   these sat on `.hero, .privacy` the footer could not see one of them — and
   `var(--hero-bg)` on a footer resolves to nothing, which paints transparent
   rather than erroring. Declared once here, used by whatever opts in. */
:root {
  /* The app's own dark ground, to the value. */
  --hero-bg: #191919;
  --hero-text: #e8e8e6;
  --hero-text-2: #9c9b97;
  --hero-text-3: #6e6d69;
  --hero-line: rgba(255, 255, 255, 0.16);

  /* The fall every light section makes from its top edge to its bottom one. */
  --sec-top: #ffffff;
  --sec-bottom: #f2f2ef;
}

.hero,
.privacy {
  text-align: center; position: relative; overflow: hidden; isolation: isolate;
  background: var(--hero-bg);
  color: var(--hero-text);
}
.hero {
  padding: calc(clamp(56px, 10vw, 104px) + var(--nav-h)) 0 clamp(56px, 8vw, 92px);
}
.hero h1, .hero .lede, .privacy h2, .privacy .lede { color: var(--hero-text); }
.hero .lede, .privacy .lede { color: var(--hero-text-2); }

/* The outline button has a light-surface border and a dark label; on this ground
   it needs the mirror of both. The gradient button is unchanged — it is the same
   gradient on any ground, which is rather the point of it. */
.hero .btn-out {
  border-color: var(--hero-line);
  color: var(--hero-text);
  background: transparent;
}
.hero .btn-out:hover { background: rgba(255, 255, 255, 0.08); border-color: rgba(255, 255, 255, 0.3); }

.hero > .wrap, .privacy > .wrap { position: relative; z-index: 1; }

/* ---- the privacy band ----
   No picture and nothing to scan: a mark, a line and a sentence, centred, with the
   glow behind them. The lede is held to a measure rather than the full column, or a
   single centred sentence runs the width of a desktop and stops reading as one line. */
.privacy .lede { max-width: 46ch; margin: 14px auto 0; }

/* THE JOIN. The ambient glow is masked to be strongest at the EDGES, so the
   band's bottom is its most colourful line — and a flat dark footer under that
   would meet it as a visible step, worst at the corners where the glow is
   brightest. This fades the last stretch of the band to the ground colour the
   footer uses, so the two become one dark region with nothing between them.
   Below `.wrap` (z-index 1) and above `.amb-glow` (z-index 0, earlier in the
   DOM), which is exactly where it needs to sit. */
.privacy::after {
  content: ''; position: absolute; inset: auto 0 0 0; height: 160px; z-index: 0;
  background: linear-gradient(to bottom, transparent, var(--hero-bg));
  pointer-events: none;
}
/* Sized by HEIGHT, because the file is a tall padlock: give it a width and the box
   is the wrong shape. `display:block` + auto margins does the centring, since the
   text-align above only moves inline boxes and this one is worth pinning. */
.privacy-mark { display: block; height: clamp(58px, 7vw, 80px); width: auto; margin: 0 auto 26px; }

/* ---- the release band: "Kordarna 2" over the Ideas sphere ----
   The same dark ground and ink as the hero and the privacy band, so the three read
   as one family, but the atmosphere here is a photograph rather than the glow: the
   app's own Ideas page, still, with its chrome hidden. The picture is `cover`, so
   on a phone the sides go and the sphere's centre stays under the words.
   Two things keep the words readable over a picture whose cards are white text on
   dark: a soft radial pool of the ground colour under the heading, and a fade to
   the ground at the top and bottom edges. The top fade is what lets this band sit
   under the hero without a seam, since both edges are then the same flat dark. */
.release {
  text-align: center; position: relative; overflow: hidden; isolation: isolate;
  background: var(--hero-bg);
  color: var(--hero-text);
  padding: clamp(84px, 12vw, 168px) 0;
}
.release-bg { position: absolute; inset: 0; z-index: 0; display: block; }
.release-bg img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: center; }
.release::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(ellipse 46% 58% at 50% 50%, rgba(25, 25, 25, 0.82), rgba(25, 25, 25, 0.3) 62%, transparent 100%),
    linear-gradient(to bottom, var(--hero-bg), transparent 18%, transparent 88%, var(--hero-bg));
}
.release > .wrap { position: relative; z-index: 1; }
/* On a phone `cover` keeps the sphere's middle and drops its sides, which brings the
   cards in under the words. The pool widens to most of the band so the words stay
   readable and the sphere stays at the edges, where it can be seen. */
@media (max-width: 720px) {
  /* `cover` on a tall box keeps a window in the middle of the picture, and the
     window's right edge reached the first storyboard frame. Slid a little left of
     centre so the frames fall outside it and more of the sphere falls inside. Tuned
     to this picture: move the frames in build-release-shot.mjs and retune. */
  .release-bg img { object-position: 40% center; }
  .release::before {
    background:
      radial-gradient(ellipse 88% 66% at 50% 50%, rgba(25, 25, 25, 0.9), rgba(25, 25, 25, 0.45) 62%, transparent 100%),
      linear-gradient(to bottom, var(--hero-bg), transparent 18%, transparent 88%, var(--hero-bg));
  }
}
/* A release is an announcement, so its title takes the hero's size, not a section's. */
.release h2 { color: var(--hero-text); font-size: clamp(38px, 6.2vw, 66px); font-weight: 680; }
/* 40ch, not the privacy band's 46: the picture has storyboards in its bottom-right
   corner, and at 1024px a 46ch lede reached them. */
.release .lede { color: var(--hero-text-2); max-width: 40ch; margin: 14px auto 0; }
.release .cta { display: flex; justify-content: center; margin-top: 30px; }

/* THE JOIN UNDER THE HERO. Its glow is strongest at the edges, so its bottom line is
   its most colourful, and a flat dark band starting right under it would meet it as
   a step. The same fade the privacy band makes into the footer, for the same reason. */
.hero::after {
  content: ''; position: absolute; inset: auto 0 0 0; height: 160px; z-index: 0;
  background: linear-gradient(to bottom, transparent, var(--hero-bg));
  pointer-events: none;
}

/* ---- the ambient glow, ported from the app ---- */

.amb-glow {
  position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none;
  /* .9 is the app's DARK-theme opacity, which is the theme this band is in. */
  opacity: 0.9;
  --ga: color-mix(in srgb, #ff5e62 50%, transparent);
  --gb: color-mix(in srgb, #b44ae0 50%, transparent);
  --gc: color-mix(in srgb, #6e6bf5 46%, transparent);
  /* Masked clear at the centre and full at the edges, so the band reads as a
     subject hanging in a dark space with light around it — and, usefully here,
     so the headline sits on the darkest part of it. */
  -webkit-mask-image: radial-gradient(ellipse 62% 58% at 50% 50%, transparent 26%, rgba(0,0,0,.5) 60%, #000 100%);
  mask-image: radial-gradient(ellipse 62% 58% at 50% 50%, transparent 26%, rgba(0,0,0,.5) 60%, #000 100%);
}
.amb-glow i { position: absolute; display: block; width: 110vmax; height: 110vmax; will-change: transform; }
.amb-glow .g1 {
  left: -45vmax; top: -50vmax;
  background:
    radial-gradient(ellipse 34% 20% at 44% 50%, var(--ga) 0%, transparent 100%),
    radial-gradient(ellipse 22% 30% at 58% 58%, var(--gb) 0%, transparent 100%);
  animation: amb-flow-a 61s ease-in-out infinite alternate;
}
.amb-glow .g2 {
  right: -50vmax; top: -40vmax;
  background:
    radial-gradient(ellipse 20% 32% at 50% 46%, var(--gb) 0%, transparent 100%),
    radial-gradient(ellipse 30% 18% at 40% 60%, var(--gc) 0%, transparent 100%);
  animation: amb-flow-b 79s ease-in-out infinite alternate;
}
.amb-glow .g3 {
  left: -20vmax; bottom: -55vmax;
  background:
    radial-gradient(ellipse 32% 22% at 52% 44%, var(--gc) 0%, transparent 100%),
    radial-gradient(ellipse 18% 28% at 42% 58%, var(--ga) 0%, transparent 100%);
  animation: amb-flow-c 97s ease-in-out infinite alternate;
}
.amb-glow .g4 {
  right: -40vmax; bottom: -45vmax;
  background:
    radial-gradient(ellipse 24% 30% at 46% 52%, var(--ga) 0%, transparent 100%),
    radial-gradient(ellipse 30% 16% at 60% 44%, var(--gb) 0%, transparent 100%);
  animation: amb-flow-a 113s ease-in-out infinite alternate-reverse;
}
/* Drift, turn, and squash-and-stretch, on periods that never line up. */
@keyframes amb-flow-a {
  0%   { transform: translate(0,0) rotate(0deg) scale(1,1) }
  50%  { transform: translate(16vmax,9vmax) rotate(38deg) scale(1.25,.8) }
  100% { transform: translate(26vmax,20vmax) rotate(-24deg) scale(.85,1.3) }
}
@keyframes amb-flow-b {
  0%   { transform: translate(0,0) rotate(10deg) scale(1.1,.9) }
  50%  { transform: translate(-14vmax,14vmax) rotate(-30deg) scale(.9,1.25) }
  100% { transform: translate(-24vmax,24vmax) rotate(28deg) scale(1.3,.85) }
}
@keyframes amb-flow-c {
  0%   { transform: translate(0,0) rotate(-12deg) scale(1,1.15) }
  50%  { transform: translate(18vmax,-12vmax) rotate(26deg) scale(1.3,.9) }
  100% { transform: translate(30vmax,-22vmax) rotate(-34deg) scale(.9,1.2) }
}
@media (prefers-reduced-motion: reduce) { .amb-glow i { animation: none } }
.hero h1 { max-width: 15ch; margin: 0 auto 20px; }
.hero .lede { margin: 0 auto; }
.hero .cta { display: flex; gap: 11px; justify-content: center; margin-top: 30px; flex-wrap: wrap; }

/* ---- THE LAPTOP (owner, 10 September 2026: "put the kordarna window in a
   laptop (preferably a Macbook Pro)") ----

   DRAWN IN CSS, not photographed. A device mockup image would be another asset to
   ship on the one view whose first paint actually matters, it would need a 2x copy
   for retina, and it would be a fixed size on a page that is fluid at every width.
   Four elements cost nothing and stay sharp everywhere.

   The proportions are a 14-inch MacBook Pro's, taken from its display: the screen
   is 3024x1964, so the screenshot's own 3200x2000 sits in it almost exactly, and
   the notch is 5.6% of the display's width. There is deliberately no logo and no
   product name anywhere on it — this is a laptop-shaped frame, not a claim about
   whose laptop it is. */
.laptop { margin-top: clamp(38px, 6vw, 62px); }

/* The lid: a thin dark bezel, the shadow that lifts the whole thing off the band,
   and a one-pixel light edge along the top where a metal lid catches the light. */
.laptop-lid {
  position: relative;
  background: #111113;
  border-radius: clamp(10px, 1.3vw, 18px);
  padding: clamp(6px, 0.85%, 12px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    0 8px 24px rgba(0, 0, 0, 0.36),
    0 30px 70px rgba(0, 0, 0, 0.45);
}

/* A PRODUCT SHOT ANYWHERE ELSE ON THE PAGE. Its own card: a hairline and the big
   soft shadow, on the light sections where those three screenshots actually sit.

   This rule was lost for two days. When the hero went dark on 10 Sep the laptop's
   screen treatment was written straight onto `.shot`, which is the class the arcs,
   script and shot-list images use as well — so all three quietly lost their border,
   their shadow and their 16px radius and sat flat on the page. Scoped properly now:
   the screen rule below is `.laptop-lid .shot`, and this one is everything else. */
.shot {
  border-radius: 16px;
  overflow: hidden;
  background: var(--bg-card);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  position: relative;
}

/* The laptop's screen. `overflow: hidden` plus a smaller radius than the lid, so the
   picture is inset within the bezel rather than sharing its corner, and no shadow or
   border of its own — the lid already provides both. */
.laptop-lid .shot {
  border-radius: clamp(4px, 0.55vw, 8px);
  border: 0;
  box-shadow: none;
}

/* The notch, drawn OVER the top-centre of the picture the way a real one intrudes
   INTO the display rather than sitting above it. It lives inside `.shot` for that
   reason: positioned against the lid instead, `top: 0` put it on the bezel's outer
   edge and it read as a tab stuck to the top of the frame. Same colour as the
   bezel, so the two still read as one continuous piece. */
.laptop-notch {
  position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: clamp(46px, 6.2%, 78px);
  height: clamp(9px, 1.05vw, 15px);
  background: #111113;
  border-radius: 0 0 clamp(4px, 0.5vw, 7px) clamp(4px, 0.5vw, 7px);
  z-index: 1;
}

/* The deck, seen head-on: a thin aluminium sliver a little wider than the lid,
   with the opening dip cut into the middle of its front edge. The gradient is
   what makes it read as metal rather than as a grey bar — light along the top
   where it meets the lid, falling away toward the front. */
.laptop-base {
  position: relative;
  /* vw, NOT a percentage. A percentage HEIGHT resolves against the parent's
     height, and `.laptop` has none to resolve against, so `clamp(10px, 1.55%, 18px)`
     computed to 0 and the deck vanished entirely. Percentages are fine for the
     horizontal overhang above, where the parent's width is definite. */
  height: clamp(10px, 1.35vw, 17px);
  margin: 0 -1.9%;
  background: linear-gradient(180deg, #b9bbc0 0%, #93959b 42%, #66686d 100%);
  border-radius: 0 0 clamp(8px, 0.9vw, 13px) clamp(8px, 0.9vw, 13px);
  box-shadow: 0 14px 28px rgba(0, 0, 0, 0.42);
}
.laptop-base span {
  position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: 12%; height: 46%;
  background: #7c7e84;
  border-radius: 0 0 clamp(5px, 0.6vw, 9px) clamp(5px, 0.6vw, 9px);
}
/* `height:auto` is not optional here. The <img> carries width/height attributes so the
   browser can reserve the right space before the file loads (no layout shift), but
   without this the attribute's 1800 is taken as a CSS height and every screenshot is
   stretched to more than twice its proper depth. */
.shot img, .shot video { width: 100%; height: auto; display: block; }

/* ---------------------------------------------------------------- sections */

/* EVERY LIGHT SECTION FALLS FROM WHITE TO A QUIET GREY (owner, 12 Sep 2026), so
   one section ends where the next begins without a rule between them.
   
   It replaces the old arrangement, where sections alternated white and a flat
   `--bg-soft` — which separated them only in pairs, and left two tinted ones
   meeting each other with nothing to show for it. A gradient separates EVERY
   boundary, because the bottom of one is always darker than the top of the next.
   
   About five percent from end to end. Enough to read as a seam on a calibrated
   screen, not enough to read as a colour. */
section {
  padding: clamp(58px, 9vw, 104px) 0;
  background: linear-gradient(180deg, var(--sec-top) 0%, var(--sec-bottom) 100%);
}
/* A SMALL WHITE STRIP BETWEEN EVERY SECTION (owner, 16 Sep 2026). Not drawn: a gap,
   with the page's own white ground showing through it. That way it is exactly the
   same strip between two dark bands as between two light ones, and no section has
   to know what its neighbour is. The hero has nothing above it but the nav, and the
   footer is not a section, so neither end gets one. */
:root { --strip: 14px; }
@media (max-width: 720px) { :root { --strip: 10px; } }
main { background: #ffffff; }
main > section + section { margin-top: var(--strip); }
.section-head { max-width: 60ch; margin-bottom: clamp(30px, 4vw, 48px); }
.section-head h2 { margin-bottom: 14px; }

/* The formats strip is the one DARK image on a light page (owner, 11 Sep 2026), so
   its card takes a dark edge. The shared `.shot` hairline is `--border`, a pale
   grey, which around a near-black picture draws a bright outline rather than an
   edge — the same mistake the hero's screenshot made when the band went dark. */
.shot.formats { background: #191919; border-color: rgba(255, 255, 255, 0.1); }

/* ---------------------------------------------------------------- types */

/* ---------------------------------------------------------------- showpiece */

/* THE WASH IS GONE (owner, 12 Sep 2026: "I don't like the colour"). This section
   used to carry a few percent of the brand gradient as atmosphere, because it
   needed to read as a change of key from its neighbours and there was nothing
   else separating them. The section gradient does that job now, for every
   boundary rather than this one, so the tint had stopped earning its place.

   Three things went, not one, and the two extras are the point: the hairlines
   above and below, which would have made this the only section with a rule
   around it, and the lilac edge on its cards, which existed to harmonise with a
   wash that no longer exists. A card here is now the same card as everywhere
   else on the page. `background` alone is left, because the rail's slides sit on
   a section that is no longer white all the way down. */
.showpiece .shot { background: var(--bg-card); }
/* ---- THE RAIL (11 September 2026) ----
   Four views of one project, scrolled sideways. CSS only: `scroll-snap` does the
   whole job, so there is no carousel script to load, nothing to break with
   JavaScript off, and the keyboard and a trackpad both already know how to drive
   a scrolling box.

   It BLEEDS past the page's own measure on purpose. A rail that stops at the text
   column reads as a box of four things; one that runs off the right edge reads as
   a row that continues, which is the only affordance telling somebody to push it.
   Negative margins of exactly the gutter, and the same padding back, so the first
   slide still lines up with the heading above it. */
.rail {
  display: flex;
  gap: 18px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  margin: 0 calc(var(--gutter) * -1);
  padding: 12px var(--gutter) 14px;
  /* scroll-padding, or the snap undoes the padding above. `scroll-snap-align:
     start` aligns a slide with the scrollport's start edge, and the scrollport
     ignores padding — so the rail silently scrolled itself 24px on load and the
     first slide sat a gutter LEFT of the heading above it. This tells the snap
     where the content really begins. */
  scroll-padding: 0 var(--gutter);
  /* Firefox and the standards track; WebKit's own bar is hidden below. */
  scrollbar-width: none;
}
.rail::-webkit-scrollbar { display: none; }
.rail figure {
  flex: 0 0 min(520px, 78vw);
  margin: 0;
  scroll-snap-align: start;
}
/* THE SHADOW HAS TO FIT INSIDE THE SCROLLPORT (owner, 11 Sep 2026: "a noticeable
   change in the background colour"; then, exactly right, "there's a drop shadow
   behind the images which is being cut off by the edge of the carousel").

   `--shadow-lg` is 0 20px 50px at 16% black. That is built for one big picture
   with the page's whole margin around it, and it does two things wrong in a row
   of cards 18px apart. It reaches 25px sideways, so the shadows of neighbouring
   slides MEET in the gap and pool into a grey band darker than either side. And
   `overflow-x: auto` makes this box a scrollport that clips at its padding edge,
   so the pool is sliced off flat at the rail's top and sides. A soft shadow that
   stops on a straight line stops reading as a shadow and starts reading as a
   change of background, which is what it looked like.

   So: the lighter token, which reaches 11px down and 7px sideways and therefore
   fits inside both the gap and the padding, with the padding opened up enough to
   clear it anyway. The cards still lift off the wash, and they do it on the
   hairline and a short shadow rather than on a big dark pool. */
.rail .shot { margin: 0; box-shadow: var(--shadow) }
/* The caption is the "small info text under each photo": a title in the page's
   own weight and a sentence under it, held to a readable measure rather than the
   full width of the slide. */
.rail figcaption {
  margin-top: 14px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-2);
  max-width: 46ch;
}
.rail figcaption b {
  display: block;
  font-size: 14.5px;
  font-weight: 650;
  color: var(--text);
  margin-bottom: 4px;
}

@media (min-width: 1120px) {
  /* Wide enough to see two and a half slides, which is the proportion that reads
     as "there is more" without the third being a sliver. */
  .rail figure { flex-basis: 560px }
}

/* ---------------------------------------------------------------- features */


/* ---------------------------------------------------------------- split */

.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(28px, 5vw, 56px); align-items: center; }
@media (max-width: 820px) { .split { grid-template-columns: 1fr; } }
.split .shot { margin-top: 0; }

/* ONE PICTURE FILLING THE SECTION'S RIGHT HALF, corner to corner (owner, 11 Sep
   2026: "make it fill from top to bottom of the section, no rounded corners").
   Square corners only read as deliberate if the panel also reaches the edge of the
   page, so it bleeds right as well as top and bottom; inset with square corners it
   would look unfinished rather than flush.

   It is positioned against the SECTION, not the wrap, and that is what makes the
   alignment exact rather than approximate. `.wrap` is centred with a max-width, so
   its own midpoint IS the section's midpoint at every viewport — which means
   `left: 50%` lands on the split's column boundary without any `100vw` arithmetic.
   A calc against `100vw` would have been a few pixels out wherever a classic
   scrollbar takes width out of the viewport but not out of the section.

   `.split` is left with a single child, so the text takes column one and column two
   stays empty for the picture to sit over. The section's height therefore still
   comes from the words, and the picture crops to whatever that turns out to be. */
.showcase { position: relative; overflow: hidden; }
.showcase-fill { position: absolute; inset: 0 0 0 calc(50% + 14px); }
.showcase-fill picture { display: block; height: 100%; }
.showcase-fill img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: left center; }

/* Stacked, the picture has no half to fill: it goes back in the flow under the
   words and keeps a shape of its own rather than covering them. */
@media (max-width: 820px) {
  .showcase-fill { position: static; inset: auto; margin-top: clamp(28px, 6vw, 44px); height: 58vw; max-height: 400px; }
}

/* ---------------------------------------------------------------- pricing */

.plans { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 15px; }
.plan {
  background: var(--bg-card); border-radius: 16px; padding: 26px 24px;
  border: 1px solid var(--border); display: flex; flex-direction: column;
}
.plan.on { border-color: transparent; box-shadow: 0 0 0 2px #b44ae0, var(--shadow); }
.plan .tier { font-size: 15px; font-weight: 650; }
.plan .price { font-size: 27px; font-weight: 660; letter-spacing: -0.03em; margin: 10px 0 3px; }
.plan .per { font-size: 12.5px; color: var(--text-3); margin-bottom: 20px; }
.plan ul { list-style: none; padding: 0; margin: 0 0 22px; }
/* The 22px above used to make room for a button under the list. The buttons went
   when the "tell me when it's ready" promise did, so the last list in a card now
   sits against the bottom padding instead of floating above a gap. */
.plan ul:last-child { margin-bottom: 0; }
.plan li {
  font-size: 13.5px; color: var(--text-2); padding: 6px 0 6px 23px; position: relative; line-height: 1.5;
}
.plan li::before {
  content: ''; position: absolute; left: 2px; top: 12px; width: 9px; height: 9px;
  border-radius: 99px; background: var(--grad-brand);
}
.plan .btn { margin-top: auto; }
.plan .tag {
  display: inline-block; font-size: 10.5px; font-weight: 640; letter-spacing: 0.07em;
  text-transform: uppercase; background: var(--grad-brand); color: #fff;
  padding: 3px 9px; border-radius: 99px; margin-left: 8px; vertical-align: 2px;
}

/* ---------------------------------------------------------------- faq */

.faq { max-width: 74ch; }
.faq details { border-bottom: 1px solid var(--border); padding: 3px 0; }
.faq summary {
  cursor: pointer; padding: 15px 0; font-size: 15px; font-weight: 610;
  list-style: none; display: flex; justify-content: space-between; gap: 20px; align-items: center;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: '+'; font-size: 19px; font-weight: 400; color: var(--text-3); flex-shrink: 0;
}
.faq details[open] summary::after { content: '−'; }
.faq p { font-size: 14px; padding: 0 0 17px; max-width: 66ch; }

/* ---------------------------------------------------------------- footer */

footer { border-top: 1px solid var(--border); padding: 42px 0 56px; }

/* DARK ON THE MAIN PAGE ONLY (owner, 12 Sep 2026), so it blends into the privacy
   band it now sits under. `body.hero-dark` is the marker the header already uses
   for the same page; Support, Privacy and Terms end on a light footer as before,
   because they end on ordinary prose rather than on a dark band.
   No border-top: a hairline between two identical grounds is the one thing that
   would announce the join this is trying to hide. */
body.hero-dark footer {
  background: var(--hero-bg);
  border-top: 0;
  color: var(--hero-text);
}
body.hero-dark footer .col h3,
body.hero-dark footer .fine { color: var(--hero-text-3); }
body.hero-dark footer .col a,
body.hero-dark footer p { color: var(--hero-text-2); }
body.hero-dark footer .col a:hover { color: var(--hero-text); }
/* The wordmark is an <img> of an SVG with `fill="#000000"` baked in, so `color`
   never reaches it — the same trap the dark nav sprang. Inverted, not recoloured. */
body.hero-dark footer .wordmark { filter: brightness(0) invert(1); }
footer .cols { display: flex; flex-wrap: wrap; gap: 44px; justify-content: space-between; }
footer svg, footer .wordmark { height: 17px; width: auto; color: var(--text); display: block; margin-bottom: 12px; }
footer .col h3 {
  font-size: 11px; font-weight: 640; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-3); margin: 0 0 11px;
}
footer .col a {
  display: block; font-size: 13.5px; color: var(--text-2); text-decoration: none; padding: 3px 0;
}
footer .col a:hover { color: var(--text); }
footer .fine { margin-top: 38px; font-size: 12px; color: var(--text-3); }

/* ------------------------------------------------------- billing toggle */

.billing { display: flex; justify-content: center; margin-bottom: 30px; }
.billing .seg {
  display: inline-flex; gap: 3px; padding: 4px; border-radius: 12px;
  background: color-mix(in srgb, var(--text) 6%, transparent);
}
.billing button {
  font: inherit; font-size: 13.5px; font-weight: 560; color: var(--text-2);
  border: 0; background: transparent; border-radius: 9px; padding: 8px 15px;
  cursor: pointer; display: inline-flex; align-items: center; gap: 8px;
  transition: color 0.15s, background 0.15s;
}
.billing button:hover { color: var(--text); }
.billing button.on { background: var(--bg); color: var(--text); box-shadow: var(--shadow); }
/* The one gradient in the section, on the one thing worth the eye going to. */
.billing .save {
  font-size: 10.5px; font-weight: 660; letter-spacing: 0.02em;
  padding: 3px 7px; border-radius: 999px; color: #fff; background: var(--grad-brand);
}

/* ------------------------------------------------------------ legal + help */

.legal { max-width: 680px; margin: 0 auto; padding: 56px 0 88px; }
.legal h1 { font-size: 38px; letter-spacing: -0.02em; margin-bottom: 10px; }
.legal .updated { font-size: 13px; color: var(--text-3); margin-bottom: 38px; }
.legal h2 {
  font-size: 19px; letter-spacing: -0.01em; margin: 40px 0 12px;
  padding-top: 26px; border-top: 1px solid var(--border);
}
.legal h3 { font-size: 15px; margin: 24px 0 8px; }
.legal p, .legal li { font-size: 15px; line-height: 1.68; color: var(--text-2); }
.legal p { margin-bottom: 14px; }
.legal ul { margin: 0 0 16px 20px; }
.legal li { margin-bottom: 8px; }
.legal strong { color: var(--text); font-weight: 620; }
.legal a { color: var(--text); text-underline-offset: 3px; }
/* A gradient button inside a legal page keeps its white words: the rule above is for
   links in running text, and it outranked `.btn-grad` by one class. */
.legal a.btn-grad { color: #fff; }
/* ---- What's new: "Kordarna 2", the release page ----
   THE WHOLE PAGE IS DARK, and one thing at a time (owner, 16 Sep 2026, after a first
   version with eight rows of prose: "take lots of inspiration from Apple's product
   pages, so the user can easily focus on one piece of information at a time"). Each
   feature is a moment: a short line, a big line, one sentence, one picture, and room
   around all of it. The moments alternate between two darks, a step apart, so the
   eye knows where one ends without a rule being drawn.

   `body.dark-page` is what the header and footer read. The bar over the home page's
   hero is dark only until it is scrolled past the band; here there is no light to
   scroll onto, so it stays dark in every state. */
body.dark-page { background: var(--hero-bg); color: var(--hero-text); }
body.dark-page main { background: var(--hero-bg); }
body.dark-page section { background: var(--hero-bg); }
/* The bar is the home page's bar over its dark band, in the same two states: nothing at
   rest, a dark translucent ground with blur once anything can pass beneath it. Those
   rules key off `body.hero-dark` and the `scrolled` class, which this page carries and
   sets too; it simply never sets `stuck`, because there is no light section to reach.
   A first version restated the bar here with its own rules and got both states wrong:
   a ground from the very top, and a hairline the home page never draws over dark. */
body.dark-page footer { background: var(--hero-bg); border-top-color: var(--hero-line); }
body.dark-page footer .col h3, body.dark-page footer .fine { color: var(--hero-text-3); }
body.dark-page footer .col a, body.dark-page footer p { color: var(--hero-text-2); }
body.dark-page footer .col a:hover { color: var(--hero-text); }
body.dark-page footer .wordmark { filter: brightness(0) invert(1); }

/* The hero: the name on plain dark, over the app's drifting glow. No picture (owner,
   16 Sep 2026). Pulled up under the bar the way the home page's hero is. */
.k2-hero {
  text-align: center; position: relative; overflow: hidden; isolation: isolate;
  background: var(--hero-bg); color: var(--hero-text);
  margin-top: calc(var(--nav-h) * -1);
  padding: calc(clamp(110px, 14vw, 190px) + var(--nav-h)) 0 clamp(110px, 14vw, 190px);
}
.k2-hero > .wrap { position: relative; z-index: 1; }
.k2-hero .eyebrow { color: var(--hero-text-2); }
.k2-hero h1 { color: var(--hero-text); font-size: clamp(56px, 10vw, 118px); font-weight: 700; letter-spacing: -0.04em; line-height: 1; margin: 0 0 22px; }
.k2-hero .lede { color: var(--hero-text-2); font-size: clamp(17px, 2.1vw, 22px); max-width: 40ch; margin: 0 auto; }
.eyebrow { font-size: 13px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--hero-text-3); margin-bottom: 16px; }

/* One moment. Centred, short, and mostly picture. */
.k2-moment { padding: clamp(84px, 12vw, 160px) 0; text-align: center; }
body.dark-page .k2-moment:nth-of-type(even) { background: #111111; }
.k2-copy { max-width: 60ch; margin: 0 auto; }
.k2-moment h2, .k2-more h2 { color: var(--hero-text); font-size: clamp(32px, 5vw, 58px); font-weight: 700; letter-spacing: -0.035em; line-height: 1.06; text-wrap: balance; margin: 0 0 18px; }
.k2-moment .lede { color: var(--hero-text-2); font-size: clamp(17px, 2vw, 21px); max-width: 44ch; margin: 0 auto; }
.k2-pic { margin-top: clamp(36px, 5vw, 64px); max-width: min(1180px, 100%); }
.k2-pic .shot { margin: 0; background: #191919; border-color: rgba(255, 255, 255, 0.1); border-radius: 18px; box-shadow: 0 30px 80px rgba(0, 0, 0, 0.5); }

/* THE COLOUR MOMENT'S PICTURE IS A BUTTON. The app's primary button, at hero size, cut
   into seven upright slices, one per primary colour, each slice the accent's own two
   stops top to bottom (theme/gradients.ts: ember, red, orchid, the Kordarna three,
   horizon, lagoon, yellow). Seven flex children rather than seven positioned
   backgrounds, so the slices are exactly equal and meet with no seam at any width. */
.k2-swatch {
  position: relative; isolation: isolate;
  height: clamp(72px, 9vw, 120px); max-width: 760px; margin: 0 auto;
  border-radius: 999px;
}
/* THE GLOW (owner, 16 Sep 2026). The same seven colours again behind the button, in
   seven hard bands, blurred wide and dimmed, so each slice throws its own light onto
   the ground the way the app's own gradient controls do. One static layer painted
   once; nothing here animates, so it costs the page nothing after first paint. The
   clip moved from the button to its bands so the glow could spill past the edge. */
.k2-swatch::before {
  content: ''; position: absolute; inset: -6px; z-index: -1; pointer-events: none;
  border-radius: 999px; filter: blur(30px); opacity: 0.6;
  background: linear-gradient(90deg,
    #FF7A58 0 14.29%, #E03A3F 14.29% 28.57%, #B356D0 28.57% 42.86%, #B44AE0 42.86% 57.14%,
    #5A72F7 57.14% 71.43%, #1FB6B6 71.43% 85.71%, #FFC60A 85.71% 100%);
}
.k2-swatch-bands {
  position: absolute; inset: 0; display: flex; border-radius: 999px; overflow: hidden;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(255, 255, 255, 0.08);
}
.k2-swatch-bands i { flex: 1 1 0; }
.k2-swatch-bands i:nth-child(1) { background: linear-gradient(180deg, #FF5E62, #FFB84D); }
.k2-swatch-bands i:nth-child(2) { background: linear-gradient(180deg, #D62828, #FF5A5F); }
.k2-swatch-bands i:nth-child(3) { background: linear-gradient(180deg, #8B5CF6, #EC4899); }
.k2-swatch-bands i:nth-child(4) { background: linear-gradient(180deg, #FF5E62, #B44AE0 55%, #6E6BF5); }
.k2-swatch-bands i:nth-child(5) { background: linear-gradient(180deg, #3B82F6, #8B5CF6); }
.k2-swatch-bands i:nth-child(6) { background: linear-gradient(180deg, #0BA5C9, #34D399); }
.k2-swatch-bands i:nth-child(7) { background: linear-gradient(180deg, #FFD60A, #FFB300); }
.k2-swatch-label {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  color: #fff; font-weight: 640; font-size: clamp(20px, 2.6vw, 30px); letter-spacing: -0.01em;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}

/* Three smaller changes with pictures, in the home page's own rail, recoloured for
   the dark ground. The rail's shadow and hairline logic is unchanged; only its inks. */
.k2-rail { padding: clamp(84px, 12vw, 160px) 0 clamp(40px, 6vw, 72px); text-align: center; }
.k2-rail .k2-copy { margin-bottom: clamp(28px, 4vw, 44px); }
.k2-rail .rail { text-align: left; }
body.dark-page .rail .shot { background: #191919; border-color: rgba(255, 255, 255, 0.1); box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45); }
body.dark-page .rail figcaption { color: var(--hero-text-2); }
body.dark-page .rail figcaption b { color: var(--hero-text); }

/* What did not earn a picture: four lines in a grid, then the one button. */
.k2-more { padding: clamp(40px, 6vw, 72px) 0 clamp(72px, 10vw, 120px); text-align: center; }
.k2-more .k2-copy { margin-bottom: clamp(36px, 5vw, 56px); }
.k2-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; text-align: left; max-width: 1180px; margin: 0 auto; }
.k2-grid > div { background: #111111; border: 1px solid var(--hero-line); border-radius: 16px; padding: 22px 22px 24px; }
.k2-grid h3 { color: var(--hero-text); font-size: 16px; margin: 0 0 8px; }
.k2-grid p { color: var(--hero-text-2); font-size: 14.5px; line-height: 1.6; margin: 0; }
.k2-more .end-cta { border-top-color: var(--hero-line); }
.k2-more .end-cta p { color: var(--hero-text-2); }
.end-cta { text-align: center; margin-top: clamp(48px, 7vw, 88px); padding-top: clamp(36px, 5vw, 56px); border-top: 1px solid var(--border); }
.end-cta p { color: var(--text-2); margin-bottom: 18px; }
.legal .back { margin-top: 44px; }

/* ---- Release notes: a sidebar of versions beside the notes ----
   Left, a list of major versions, each a bold title with a chevron that folds its
   releases away, newest first; right, the notes, one article per release. The
   sidebar stays put while the notes scroll. On a phone it stacks above the notes
   and stops sticking, since there is no room beside them. */
.vh { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: clamp(32px, 5vw, 72px); align-items: start; padding-top: 56px; }
.vh .legal { padding-top: 0; margin: 0; max-width: 680px; }
.vh-side { position: sticky; top: calc(var(--nav-h) + 24px); }
.vh-side details { border-bottom: 1px solid var(--border); padding: 4px 0 10px; }
.vh-side summary {
  cursor: pointer; list-style: none; display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 10px 0; font-size: 15px; font-weight: 650; color: var(--text);
}
.vh-side summary::-webkit-details-marker { display: none; }
/* The chevron: a rotated square's two edges, turning to point down when open. */
.vh-side summary::after {
  content: ''; width: 7px; height: 7px; flex-shrink: 0; margin-right: 4px;
  border-right: 1.5px solid var(--text-3); border-bottom: 1.5px solid var(--text-3);
  transform: rotate(-45deg); transition: transform .18s;
}
.vh-side details[open] summary::after { transform: rotate(45deg); }
.vh-side a {
  display: flex; justify-content: space-between; gap: 10px; align-items: baseline;
  padding: 6px 0 6px 12px; font-size: 14px; font-weight: 600; color: var(--text); text-decoration: none;
  border-left: 2px solid transparent; border-radius: 0 6px 6px 0;
}
.vh-side a span { font-size: 12px; font-weight: 400; color: var(--text-3); white-space: nowrap; }
.vh-side a:hover { background: var(--bg-soft); }
.vh-side a:target, .vh-side a.current { border-left-color: var(--text); }
/* One release. Its number is the big heading; the areas inside it take the smaller,
   ruled heading the legal pages use for their sections. */
.release-note { scroll-margin-top: calc(var(--nav-h) + 20px); padding-top: 8px; }
.release-note + .release-note { margin-top: 56px; border-top: 1px solid var(--border); padding-top: 40px; }
.release-note h2 { font-size: 30px; letter-spacing: -0.02em; margin: 0 0 4px; padding: 0; border: 0; }
.release-note .release-date { font-size: 13px; color: var(--text-3); margin-bottom: 18px; }
.release-note h3 { font-size: 17px; letter-spacing: -0.01em; margin: 34px 0 10px; padding-top: 22px; border-top: 1px solid var(--border); }
@media (max-width: 860px) {
  .vh { grid-template-columns: 1fr; gap: 28px; padding-top: 40px; }
  .vh-side { position: static; }
  .vh-side details { border-bottom: 0; }
}

/* A note the reader should see, not a warning: used where the honest answer is
   less comfortable than the marketing one. */
.legal .note {
  background: var(--bg-soft); border-radius: 12px; padding: 16px 18px; margin: 0 0 18px;
}
.legal .note p:last-child { margin-bottom: 0; }

.help-form { max-width: 680px; margin: 0 auto; }
.help-form label { display: block; font-size: 13px; font-weight: 620; margin: 18px 0 6px; }
.help-form input, .help-form textarea, .help-form select {
  width: 100%; font: inherit; font-size: 14.5px; color: var(--text);
  background: var(--bg); border: 1px solid var(--border); border-radius: 10px;
  padding: 11px 13px;
}
.help-form textarea { min-height: 168px; resize: vertical; line-height: 1.6; }
.help-form input:focus, .help-form textarea:focus { outline: none; border-color: #b44ae0; }
.help-form .row { display: flex; gap: 14px; flex-wrap: wrap; }
.help-form .row > div { flex: 1 1 240px; }
.form-msg { margin-top: 14px; font-size: 14px; }
.form-msg.ok { color: #0a7d4f; }
.form-msg.bad { color: #b3261e; }

/* Tutorials share the FAQ's collapsible rows, with room for real paragraphs
   inside rather than a single sentence. */
.legal .tut { margin: 4px 0 8px; }
.legal .tut details { border-bottom: 1px solid var(--border); }
.legal .tut summary {
  cursor: pointer; padding: 15px 0; font-size: 15px; font-weight: 600; color: var(--text);
  list-style: none; display: flex; align-items: center; gap: 10px;
}
.legal .tut summary::-webkit-details-marker { display: none; }
.legal .tut summary::before {
  content: ''; width: 7px; height: 7px; flex: none;
  border-right: 1.5px solid var(--text-3); border-bottom: 1.5px solid var(--text-3);
  transform: rotate(-45deg); transition: transform 0.15s;
}
.legal .tut details[open] summary::before { transform: rotate(45deg); }
.legal .tut details > p { margin: 0 0 12px 17px; font-size: 14.5px; }
.legal .tut details > p:last-child { margin-bottom: 16px; }

/* ---------------------------------------------------------- accessibility */

/* Off-screen until focused, then the first thing a keyboard reaches. */
.skip-link {
  position: absolute; left: 12px; top: -60px; z-index: 100;
  background: var(--bg); color: var(--text); border: 1px solid var(--border);
  border-radius: 10px; padding: 10px 16px; font-size: 14px; font-weight: 600;
  text-decoration: none; box-shadow: var(--shadow-lg); transition: top 0.15s;
}
.skip-link:focus { top: 12px; }
#main:focus { outline: none; }

/* One visible focus ring for everything, since several of these elements had
   none of their own and a keyboard user cannot see where they are without it.
   :focus-visible rather than :focus, so a mouse click does not draw a ring
   nobody asked for. */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
input:focus-visible,
textarea:focus-visible {
  outline: 2px solid #7c4dd0;
  outline-offset: 3px;
  border-radius: 6px;
}

/* The wordmark in the header is the way home, which is where everyone looks for
   it. The footer's copy stays a plain image: a second link to the same place,
   announced identically, is noise in a screen reader's list of links. */
header .home { display: flex; align-items: center; border-radius: 6px; }
header .home:hover { opacity: 0.72; }

/* ---- launch day: the app is somewhere to go ----
   The site had no link to the app because there was no app to link to. */

/* The nav's last item is the one that leaves the marketing site, so it reads as
   a destination rather than another anchor down the page — but since 10 Sep 2026
   it says so with WEIGHT AND COLOUR rather than a bordered pill. The pill was the
   single thing making a 44px bar look tall: it was the only padded item, so it set
   the bar's minimum height and drew a hard edge across an otherwise open strip.
   Apple's own nav has no button in it either. The hero's gradient CTA is still the
   loud one, which is where the loudness belongs. */
.nav-app {
  font-weight: 600;
  color: var(--text);
  transition: opacity .15s;
}
.nav-app:hover { opacity: 0.6; }

.band-cta { margin-top: 22px }
.band-note { margin-top: 18px; font-size: 13px; color: var(--text-3) }


