/* ==========================================================================
   Sonic Refine — public site stylesheet
   Hand-written, no framework, no build step.

   The palette is the desktop app's palette, not a website interpretation of
   it: obsidian, electric cyan, one violet for the second voice. Someone who
   downloads after reading this page should recognise the thing that opens.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Design tokens

   Two layers, deliberately.

   The *palette* below is raw colour and nothing outside this block may
   reference it. Everything else in the file — and every view — uses the
   *semantic* tokens underneath it. That separation is what makes a theme
   twenty redefinitions rather than an audit of four thousand lines.

   DARK IS THE BASE, NOT THE OVERRIDE.

   That is the one structural change from the previous palette. The app is
   obsidian and only obsidian; a site that opens white and turns dark on
   request would spend most of its visits looking like a different product.
   So `:root` is the dark theme, and light exists only for a visitor who asks
   for it by pressing the switch — `[data-theme="light"]`. There is no
   `prefers-color-scheme` branch, because the OS preference is not a statement
   about this brand.

   The older --ink-* / --brand-* / --paper names are kept at the end of the
   block as aliases onto the semantic layer, so pages written before this
   palette existed pick it up (and theme correctly) without being touched.
   -------------------------------------------------------------------------- */

:root {
    color-scheme: dark;

    /* Palette — obsidian. The room the site sits in. Lifted one or two points
       from the app's values: a browser window has no title bar of ours around
       it, so the ground can afford to be a shade less absolute. */
    --p-obsidian:  #07080b;
    --p-void:      #050609;
    --p-panel:     #0c0f13;
    --p-panel-2:   #11151a;
    --p-raise:     #161b22;
    --p-raise-2:   #1c222b;

    /* Palette — cool neutrals, for the light theme and for anything that needs
       a grey that is not a transparency over the ground. */
    --p-white:   #ffffff;
    --p-n-25:    #fafcfd;
    --p-n-50:    #f2f6f8;
    --p-n-100:   #e6ecf1;
    --p-n-200:   #d5dee5;
    --p-n-300:   #b6c3ce;
    --p-n-400:   #8a94a5;
    --p-n-500:   #5c6675;
    --p-n-600:   #454e5c;
    --p-n-700:   #313947;
    --p-n-800:   #1f2530;
    --p-n-900:   #12161d;
    --p-n-950:   #0a0d12;

    /* Palette — electric cyan. The one colour that means "this is live, or
       this is next". Rationed on purpose: a palette where six things glow is a
       palette where nothing does. */
    --p-cyan-200: #b6f3fc;
    --p-cyan-300: #7ceaf9;
    --p-cyan-400: #22d3ee;
    --p-cyan-500: #0eaecb;
    --p-cyan-600: #0b7f92;
    --p-cyan-700: #086372;
    --p-cyan-800: #064a56;
    --p-cyan-ink: #04161c;

    /* Palette — violet. The finishing touch, third in the order after obsidian
       and cyan: an edge, a badge, one icon tile — never a surface and never a
       whole section. The values match the desktop app's own violet
       (`--violet` / `[data-accent='violet']` in src/renderer/styles.css) so the
       two products are drawing the same colour. 700 and 800 exist only for the
       light theme, where #a78bfa on white is 2.1:1 and cannot carry text. */
    --p-violet-200: #e4dcff;
    --p-violet-300: #c9b8ff;
    --p-violet-400: #a78bfa;
    --p-violet-500: #8b5cf6;
    --p-violet-600: #6d4fd6;
    --p-violet-700: #5a3fb8;
    --p-violet-800: #452f8f;
    --p-violet-ink: #120a24;

    /* Palette — status. The app's own three. */
    --p-green-100: #d3f7e0;
    --p-green-200: #a3ecc0;
    --p-green-400: #4ade80;
    --p-green-600: #12784a;
    --p-green-800: #0c3a26;

    --p-amber-100: #fdf1d8;
    --p-amber-200: #f6dda6;
    --p-amber-400: #fbbf24;
    --p-amber-600: #94590a;
    --p-amber-800: #45320d;

    --p-red-100:   #ffe4e8;
    --p-red-200:   #fdc7ce;
    --p-red-400:   #fb7185;
    --p-red-600:   #c22a41;
    --p-red-800:   #4a1a22;

    /* ---- Semantic: surfaces ---- */
    --bg:            var(--p-obsidian);
    --bg-subtle:     var(--p-panel);
    --bg-inset:      var(--p-panel-2);
    --surface:       var(--p-panel);
    --surface-raised: var(--p-raise);
    --surface-invert: var(--p-n-50);

    /* ---- Semantic: lines ----
       Transparencies rather than colours, so a card on the raised surface and
       a card on the ground both get a border that reads as the same weight. */
    --line:          rgba(255, 255, 255, .07);
    --line-strong:   rgba(255, 255, 255, .14);
    --line-invert:   rgba(0, 0, 0, .12);

    /* ---- Semantic: text ---- */
    --text:           #eef2f7;
    --text-secondary: #c3cbd7;
    --text-muted:     #8a94a5;
    --text-invert:    var(--p-n-900);
    /* Cyan is a bright accent. Text sitting on it is ink, never white — white
       on #22d3ee is a 1.7:1 contrast ratio and unreadable at any size.
       The four tokens under it are the rest of that panel's kit: secondary
       text, a divider, a tint, and the button that sits on top of it. They
       exist because every one of those used to be a hard-coded white, which was
       correct when the panel was dark indigo and became invisible the moment it
       became bright cyan. */
    --text-on-accent:  var(--p-cyan-ink);
    --on-accent-muted: rgba(4, 22, 28, .72);
    --on-accent-line:  rgba(4, 22, 28, .32);
    --on-accent-fill:  rgba(4, 22, 28, .10);
    --on-accent-btn:   var(--p-obsidian);
    --on-accent-btn-fg: var(--p-cyan-300);

    /*
      ---- Semantic: accent ----

      Obsidian is the main colour of this site. Cyan is the accent on top of it,
      and violet is the finishing touch on top of that — a strict order, and the
      reason the big cyan wash that used to cover the top of every page had to
      go: at that size an accent stops being an accent and becomes the
      background, which left the product looking cyan rather than obsidian.

      Rationed on purpose. A palette where six things glow is a palette where
      nothing does.
    */
    --accent:        var(--p-cyan-400);
    --accent-hover:  var(--p-cyan-300);
    --accent-soft:   rgba(34, 211, 238, .12);
    --accent-softer: rgba(34, 211, 238, .20);
    --accent-line:   rgba(34, 211, 238, .34);
    --accent-text:   var(--p-cyan-300);
    --accent-glow:   rgba(34, 211, 238, .30);
    --ring:          rgba(34, 211, 238, .55);

    /* ---- Semantic: the second accent ----
       Violet, used only where it says something cyan cannot: video against
       audio, a warning that is not an error, one edge on a card. Finishing
       touches — never a surface, never a whole section. */
    --violet:        var(--p-violet-400);
    --violet-soft:   rgba(167, 139, 250, .14);
    --violet-line:   rgba(167, 139, 250, .32);
    --violet-text:   var(--p-violet-300);

    /* ---- Semantic: status ---- */
    --success-bg:   rgba(74, 222, 128, .13);
    --success-line: rgba(74, 222, 128, .30);
    --success-fg:   var(--p-green-400);
    --warning-bg:   rgba(251, 191, 36, .13);
    --warning-line: rgba(251, 191, 36, .30);
    --warning-fg:   var(--p-amber-400);
    --danger-bg:    rgba(251, 113, 133, .13);
    --danger-line:  rgba(251, 113, 133, .30);
    --danger-fg:    var(--p-red-400);

    /*
      ---- Gradients ----

      WHY THE BIG WASHES ARE GONE.

      The old --grad-mesh laid a 40rem-wide radial gradient across the top of
      the hero, the account band and every auth screen. Two things were wrong
      with it, and they compounded.

      It banded. A wide, low-alpha ramp over near-black has to step through
      about 640px of colour in 8-bit increments, and the eye reads those steps
      as concentric rings — the "low res" look. Nothing about the code was
      low resolution; the display simply has no in-between colours to use.

      And it inverted the palette. A colour wash covering the top third of the
      page stops being an accent and becomes the background, which left cyan
      reading as the main colour of a product whose main colour is obsidian.

      So the washes are now small, faint, and dithered by --grain. Small is the
      real fix: a short ramp has fewer steps to show. The grain covers the rest
      by scattering the boundary between one step and the next, which is the
      same trick print uses. Obsidian gets to be the main colour again.
    */
    --grad-brand: linear-gradient(135deg, var(--p-cyan-300), var(--p-cyan-500));
    --grad-duo:   linear-gradient(120deg, var(--p-cyan-400) 0%, var(--p-cyan-300) 42%, var(--p-violet-400) 100%);

    /* A tight bloom, not a wash. Sits behind one card, never a whole section. */
    --grad-spot:  radial-gradient(26rem 14rem at 50% -20%, rgba(34, 211, 238, .09), transparent 62%);

    /* Two small blooms at the very top edge — cyan leading, violet as the
       finishing touch beside it, so the page opens on obsidian with a hint of
       colour rather than on a field of it. */
    --grad-mesh:
        radial-gradient(26rem 13rem at 16% -12%, rgba(34, 211, 238, .12), transparent 60%),
        radial-gradient(20rem 11rem at 86% -8%, rgba(167, 139, 250, .07), transparent 58%);

    /*
      The dither layer.

      A 220px tile of fine fractal noise laid over the two large washes, and
      nothing else. It exists to scatter the boundary between one 8-bit step and
      the next, which is what stops a wide ramp drawing visible rings.

      IT WAS THREE TIMES THIS STRONG AND YOU COULD SEE IT.

      Noise reads far louder on near-black than the same value does on white:
      every lit pixel is the brightest thing in its neighbourhood, so 5% opacity
      that would vanish on a light page shows up as texture on obsidian. It is
      now .018 — below the threshold where the eye resolves individual specks,
      but still enough to break up a ramp, because dithering works at strengths
      well under the level at which you can see the dither itself.

      The tile also went from 140px to 220px with a lower baseFrequency, so the
      pattern is finer and repeats less often. Inline SVG: no request, no 404.
    */
    --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.75' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)' opacity='.018'/%3E%3C/svg%3E");

    /* ---- Radii. The app's scale, one step up: web cards are bigger. ---- */
    --radius-sm: 8px;
    --radius-md: 13px;
    --radius-lg: 18px;
    --radius-xl: 26px;
    --radius-pill: 999px;

    /* ---- Elevation. On obsidian a shadow is real black, not tinted ink. ---- */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .45);
    --shadow-md: 0 8px 20px rgba(0, 0, 0, .45), 0 2px 6px rgba(0, 0, 0, .35);
    --shadow-lg: 0 28px 64px -20px rgba(0, 0, 0, .85), 0 6px 18px rgba(0, 0, 0, .45);
    --shadow-accent: 0 10px 30px -6px rgba(34, 211, 238, .40);

    /* ---- Space ---- */
    --space-1: .25rem;
    --space-2: .5rem;
    --space-3: .75rem;
    --space-4: 1rem;
    --space-6: 1.5rem;
    --space-8: 2rem;
    --space-12: 3rem;
    --space-16: 4rem;
    --space-24: 6rem;

    --font-sans: "Inter var", Inter, system-ui, -apple-system, "Segoe UI Variable Text",
                 "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --font-display: "Inter var", Inter, "Segoe UI Variable Display", system-ui,
                    -apple-system, "Segoe UI", sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

    --measure: 68ch;
    --container: 1180px;

    --ease: cubic-bezier(.4, 0, .2, 1);
    --ease-out: cubic-bezier(.16, 1, .3, 1);
    /* The app's own easing, for anything that mimics an app interaction. */
    --ease-app: cubic-bezier(.22, .61, .36, 1);

    /* Height of the sticky header, so full-height layouts can subtract it
       instead of guessing. Kept in sync with .site-header__inner. */
    --header-h: 72px;

    /* ---- Legacy aliases ----------------------------------------------------
       Kept so pre-existing markup themes correctly. New CSS should use the
       semantic tokens above. */
    --ink-900: var(--text);
    --ink-700: var(--text-secondary);
    --ink-500: var(--text-secondary);
    --ink-300: var(--text-muted);
    --ink-200: var(--line-strong);
    --ink-100: var(--line);
    --ink-50:  var(--bg-inset);

    --paper: var(--surface);

    --brand-600: var(--accent);
    --brand-500: var(--p-cyan-300);
    --brand-100: var(--accent-soft);

    --ok-600:   var(--success-fg);
    --ok-100:   var(--success-bg);
    --warn-600: var(--warning-fg);
    --warn-100: var(--warning-bg);
    --err-600:  var(--danger-fg);
    --err-100:  var(--danger-bg);
}

/* --------------------------------------------------------------------------
   Light theme — opt-in only.

   Reached by pressing the switch in the header, never by an OS preference.
   Cyan cannot survive the trip unchanged: #22d3ee on white is a 1.9:1 contrast
   ratio, so the accent moves down the same ramp to its 600 step, which is the
   same hue at a weight that can carry white text and be read as a link.
   -------------------------------------------------------------------------- */

:root[data-theme="light"] {
    color-scheme: light;

    --bg:            var(--p-white);
    --bg-subtle:     var(--p-n-50);
    --bg-inset:      var(--p-n-100);
    --surface:       var(--p-white);
    --surface-raised: var(--p-white);
    --surface-invert: var(--p-n-900);

    --line:          var(--p-n-200);
    --line-strong:   var(--p-n-300);
    --line-invert:   rgba(255, 255, 255, .14);

    --text:           var(--p-n-900);
    --text-secondary: var(--p-n-600);
    --text-muted:     var(--p-n-500);
    --text-invert:    var(--p-white);
    /* The light theme's accent panel is deep teal, so the polarity flips: white
       text, white dividers, and a white button on top of it. */
    --text-on-accent:  var(--p-white);
    --on-accent-muted: rgba(255, 255, 255, .84);
    --on-accent-line:  rgba(255, 255, 255, .45);
    --on-accent-fill:  rgba(255, 255, 255, .16);
    --on-accent-btn:   var(--p-white);
    --on-accent-btn-fg: var(--p-cyan-700);

    --accent:        var(--p-cyan-600);
    --accent-hover:  var(--p-cyan-700);
    --accent-soft:   rgba(11, 127, 146, .09);
    --accent-softer: rgba(11, 127, 146, .16);
    --accent-line:   rgba(11, 127, 146, .26);
    --accent-text:   var(--p-cyan-700);
    --accent-glow:   rgba(11, 127, 146, .28);
    --ring:          rgba(11, 127, 146, .45);

    /* Violet stays the finishing touch here too, at a weight white text
       survives — #5a3fb8 on white is 7:1, where the 400 step would be 2.1:1. */
    --violet:        var(--p-violet-700);
    --violet-soft:   rgba(90, 63, 184, .09);
    --violet-line:   rgba(90, 63, 184, .24);
    --violet-text:   var(--p-violet-700);

    --success-bg:   var(--p-green-100);
    --success-line: var(--p-green-200);
    --success-fg:   var(--p-green-600);
    --warning-bg:   var(--p-amber-100);
    --warning-line: var(--p-amber-200);
    --warning-fg:   var(--p-amber-600);
    --danger-bg:    var(--p-red-100);
    --danger-line:  var(--p-red-200);
    --danger-fg:    var(--p-red-600);

    /* Deep enough to carry white text at body size — #086372 against white is
       6:1, where the 500 step this used to start on was 2.4:1. */
    --grad-brand: linear-gradient(135deg, var(--p-cyan-700), var(--p-cyan-800));
    --grad-duo:   linear-gradient(120deg, var(--p-cyan-600) 0%, var(--p-cyan-500) 45%, var(--p-violet-500) 100%);
    --grad-spot:  radial-gradient(26rem 14rem at 50% -20%, rgba(11, 127, 146, .07), transparent 62%);
    --grad-mesh:
        radial-gradient(26rem 13rem at 16% -12%, rgba(34, 211, 238, .13), transparent 60%),
        radial-gradient(20rem 11rem at 86% -8%, rgba(167, 139, 250, .08), transparent 58%);

    /*
      No grain in the light theme.

      Banding is a dark-theme problem. A ramp on white starts from a value with
      plenty of headroom above it and the steps land close together, so there
      are no rings to dither away — which leaves noise on a white page as cost
      with no benefit, and it is more visible there than the numbers suggest
      because the eye is not busy adapting to a dark field.

      `none` rather than a very low opacity: the background shorthand accepts it
      as an empty layer, so the rule below stays one declaration in both themes.
    */
    --grain: none;

    --shadow-sm: 0 1px 2px rgba(18, 22, 29, .05), 0 1px 3px rgba(18, 22, 29, .04);
    --shadow-md: 0 6px 16px rgba(18, 22, 29, .07), 0 2px 6px rgba(18, 22, 29, .05);
    --shadow-lg: 0 18px 40px rgba(18, 22, 29, .10), 0 6px 14px rgba(18, 22, 29, .06);
    --shadow-accent: 0 8px 24px rgba(11, 127, 146, .26);

    --ink-700: var(--p-n-700);
    --ink-500: var(--text-secondary);
}

/* --------------------------------------------------------------------------
   2. Reset and base
   -------------------------------------------------------------------------- */

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
    /* Anchored sections must clear the sticky header. */
    scroll-padding-top: 6rem;
}

body {
    margin: 0;
    font-family: var(--font-sans);
    font-size: 1rem;
    line-height: 1.65;
    color: var(--ink-700);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-feature-settings: "cv02", "cv03", "cv04", "ss01";
}

h1, h2, h3, h4 {
    margin: 0 0 var(--space-4);
    line-height: 1.15;
    color: var(--text);
    font-weight: 640;
    letter-spacing: -.02em;
    text-wrap: balance;
}

p {
    margin: 0 0 var(--space-4);
    max-width: var(--measure);
    text-wrap: pretty;
}

a {
    color: var(--accent-text);
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
    transition: color .15s var(--ease);
}

a:hover {
    color: var(--accent);
}

code {
    font-family: var(--font-mono);
    font-size: .9em;
    background: var(--bg-inset);
    padding: .15em .4em;
    border-radius: var(--radius-sm);
}

img {
    max-width: 100%;
    height: auto;
}

::selection {
    background: var(--accent-softer);
    color: var(--text);
}

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 100;
    padding: var(--space-3) var(--space-4);
    background: var(--accent);
    color: var(--text-on-accent);
    border-radius: 0 0 var(--radius-md) 0;
}

.skip-link:focus {
    left: 0;
}

.container {
    width: 100%;
    max-width: var(--container);
    margin-inline: auto;
    padding-inline: var(--space-6);
}

/* --------------------------------------------------------------------------
   3. Header and navigation

   One bar, three zones: brand, links, actions. Below 960px the links and the
   actions collapse behind a single button — two separate collapsing regions
   would mean two things to keep in sync and two ways to trap focus.
   -------------------------------------------------------------------------- */

/* Slim strip above the header. Carries one message and one link; anything more
   competes with the navigation for the same glance. */
/*
  Quiet, since the header stopped being a bar.

  This was a full-bleed cyan gradient. Above a floating capsule it fought it for
  the same job — a saturated strip pinned to the very top edge re-establishes
  exactly the welded-to-the-viewport line the capsule exists to get away from,
  and it put the loudest colour on the page in the first 30 pixels.

  It is obsidian now, with the accent reduced to a single dot before the text.
  Same message, and the eye goes to the capsule instead.
*/
.promo-bar {
    position: relative;
    z-index: 25;
    background: var(--p-void);
    border-bottom: 1px solid var(--line);
    color: var(--text-secondary);
    font-size: .8125rem;
}

.promo-bar__text::before {
    content: "";
    display: inline-block;
    width: 5px;
    height: 5px;
    margin-right: .5rem;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 8px var(--accent-glow);
    vertical-align: middle;
}

.promo-bar__inner {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2) var(--space-3);
    flex-wrap: wrap;
    padding-block: .5rem;
    text-align: center;
}

/* The strip is obsidian now, so these are accent-on-dark rather than
   ink-on-accent. Left as they were, both would have been near-black text on a
   near-black bar. */
.promo-bar__link {
    color: var(--accent-text);
    font-weight: 600;
    text-decoration: none;
    border-bottom: 1px solid var(--accent-line);
}

.promo-bar__link:hover {
    color: var(--accent-hover);
    border-bottom-color: currentColor;
}

/*
  A FLOATING PILL, NOT A BAR.

  The header used to be a full-bleed strip welded to the top of the viewport
  with a hairline under it — the default every site arrives at, and the reason
  the page read as a template rather than a product.

  It is now a capsule that sits inset from all three edges with the page
  visibly running underneath it. Two things make that work and both matter:
  the radius has to be a true pill (half the height, not a "rounded" 16px,
  which just looks like a bar with the corners filed off), and the fill has to
  be translucent with a blur so you can see content moving beneath it. A solid
  capsule floating over the page is a floating bar; a translucent one is glass.

  The lift is what sells it. Sitting the capsule ON the hero rather than above
  it means the hero's own colour shows through the glass, so the header takes
  its tint from whatever page it is on instead of being a fixed slab.
*/
/*
  Sticky, and deliberately NOT pulled over the content with a negative margin.

  Floating the capsule on top of the page below it looks right on a hero that
  was designed around it and wrong on all fourteen other page types, where it
  would sit on a heading. Sticky-with-an-offset gives the same floating capsule
  and the same glass, without any page having to reserve room for it.
*/
.site-header {
    position: sticky;
    top: var(--space-3);
    z-index: 20;
    margin-block: var(--space-3) var(--space-2);
    padding-inline: var(--space-4);
}

.site-header__inner {
    display: flex;
    align-items: center;
    gap: var(--space-6);
    min-height: 64px;
    max-width: calc(var(--container) + var(--space-8));
    margin-inline: auto;
    padding-inline: var(--space-3) var(--space-3);

    border: 1px solid var(--line-strong);
    border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--bg) 72%, transparent);
    backdrop-filter: saturate(180%) blur(18px);
    -webkit-backdrop-filter: saturate(180%) blur(18px);
    box-shadow:
        0 1px 0 rgba(255, 255, 255, .05) inset,
        0 18px 40px -22px rgba(0, 0, 0, .85);
    transition: background-color .25s var(--ease), border-color .25s var(--ease),
                box-shadow .25s var(--ease);
}

/*
  Scrolled. The capsule tightens rather than growing a border: it gets more
  opaque so text stays readable over whatever is passing beneath, and the
  shadow deepens so it reads as having lifted further off the page.
*/
.site-header.is-stuck .site-header__inner {
    background: color-mix(in srgb, var(--bg) 90%, transparent);
    border-color: var(--line-strong);
    box-shadow:
        0 1px 0 rgba(255, 255, 255, .06) inset,
        0 22px 50px -20px rgba(0, 0, 0, .95);
}

/* The brand needs to clear the capsule's own rounding. */
.site-header .brand { padding-left: var(--space-3); }

@media (max-width: 960px) {
    /* Collapsed, the panel unrolls out of the capsule, so the capsule stops
       being a capsule and becomes a card. A pill with a list hanging out of
       the bottom of it is the one state this shape cannot hold. */
    .site-header__inner {
        border-radius: var(--radius-xl);
        padding-inline: var(--space-4);
    }
}

.brand {
    display: inline-flex;
    align-items: center;
    gap: .625rem;
    font-weight: 680;
    font-size: 1.0625rem;
    color: var(--text);
    text-decoration: none;
    letter-spacing: -.025em;
    flex: none;
}

.brand:hover { color: var(--text); }

/*
  THE LOGO, IN BOTH INKS, AND NO ARITHMETIC LEFT.

  img/logo-on-dark.png and img/logo-on-light.png are the supplied artwork, byte
  for byte — the same pair the desktop app's icons are built from.

  They are NOT the same shape, and that is deliberate rather than an oversight
  to work around. Measured from their own alpha channels:

    on-dark   the bare mark, white. 488 x 400 at 12,56 of 512, 57% transparent
    on-light  a black rounded tile, white mark inside. Full bleed, 3% clear

  A bare mark is right on a dark ground and a tile is right on a light one, so
  each file is drawn for its own job. What they DO share is the only thing this
  rule needs: both are square 512 canvases with the artwork centred on the
  centre pixel. So the wrapper is one fixed square, both images fill it, and
  neither theme needs an offset, a crop or a size of its own.

  38px, because the on-dark mark is 400/512 of its canvas and 38 x 400/512 =
  29.7 — the 30px tall mark the header was built around. A FIXED box in both
  themes is the point: the previous version resized the wrapper for the light
  theme and the header jumped every time the toggle was pressed.

  There is no plate in this file any more. The light theme used to get an
  obsidian rectangle drawn behind the white mark here, as a stand-in for a
  variant that did not exist. It exists now, and it brought its own.
*/
.brand__mark {
    position: relative;
    display: block;
    width: 38px;
    height: 38px;
    flex: none;
}

.brand__mark .brand__mark-ink {
    display: block;
    width: 38px;
    height: 38px;
    /* The base reset caps images at `max-width: 100%`. Harmless at this size,
       but stated so a narrower wrapper later cannot silently shrink the mark. */
    max-width: none;
}

/*
  ONE INK AT A TIME, and only the hidden one is ever named.

  Both files are in the markup and the theme decides. Note that neither rule
  sets `display` on the ink that SHOWS — it is left to whatever its context
  gives it, which is how the same two classes serve the header (absolutely
  positioned, 38.4px) and the auth screens (in flow, 24px) without either
  needing to know about the other.

  Decided in CSS rather than by script: the theme is resolved before first
  paint, so a `src` swapped from JavaScript would paint the wrong ink for a
  frame on every load — and on the light theme that frame is a blank gap.
*/
:root:not([data-theme="light"]) .brand__mark-ink--on-light { display: none; }
:root[data-theme="light"] .brand__mark-ink--on-dark { display: none; }

.brand__name {
    white-space: nowrap;
    font-family: var(--font-display);
    font-weight: 660;
    letter-spacing: -.028em;
}

.site-header__collapse {
    display: flex;
    align-items: center;
    gap: var(--space-6);
    flex: 1 1 auto;
    justify-content: space-between;
}

.site-nav {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    font-size: .9375rem;
}

.site-nav a {
    position: relative;
    padding: .5rem .75rem;
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    font-weight: 500;
    text-decoration: none;
    white-space: nowrap;
    transition: color .15s var(--ease), background-color .15s var(--ease);
}

.site-nav a:hover {
    color: var(--text);
    background: var(--bg-inset);
}

.site-nav a.is-current {
    color: var(--text);
    font-weight: 600;
}

/* The marker sits under the label rather than filling the pill, so the current
   page is legible at a glance without shouting over the primary action. */
.site-nav a.is-current::after {
    content: "";
    position: absolute;
    left: .75rem;
    right: .75rem;
    bottom: .2rem;
    height: 2px;
    border-radius: 2px;
    background: var(--accent);
}

.site-nav__pending {
    color: var(--text-muted);
    cursor: not-allowed;
}

.site-header__actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

/* Theme switch. Both glyphs are in the DOM; CSS shows whichever matches the
   theme in force, so there is no flash of the wrong icon and no JS involved in
   drawing it. */
.theme-toggle {
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    flex: none;
    padding: 0;
    color: var(--text-secondary);
    background: transparent;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: color .15s var(--ease), border-color .15s var(--ease),
                background-color .15s var(--ease);
}

.theme-toggle:hover {
    color: var(--text);
    border-color: var(--line-strong);
    background: var(--bg-inset);
}

.theme-toggle svg { width: 17px; height: 17px; }

/* Every rule below is written with the element selector included, because
   `.theme-toggle svg` above outranks a bare class and would keep both glyphs
   on screen.

   The button shows the theme you are IN, not the one you would get. Dark is
   the default now, so the moon is the default glyph and light is the single
   exception — there is no OS-preference branch to keep in step any more. */
.theme-toggle svg.theme-toggle__moon { display: block; }
.theme-toggle svg.theme-toggle__sun { display: none; }

:root[data-theme="light"] .theme-toggle svg.theme-toggle__moon { display: none; }
:root[data-theme="light"] .theme-toggle svg.theme-toggle__sun { display: block; }

/* ------------------------------------------------------------- User menu */

.user-menu { position: relative; }

.user-menu__trigger {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    padding: .3rem .6rem .3rem .3rem;
    font: inherit;
    font-size: .875rem;
    font-weight: 550;
    color: var(--text);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-pill);
    cursor: pointer;
    transition: border-color .15s var(--ease), background-color .15s var(--ease);
}

.user-menu__trigger:hover { border-color: var(--line-strong); background: var(--bg-inset); }

.user-menu__avatar {
    display: grid;
    place-items: center;
    width: 28px;
    height: 28px;
    flex: none;
    border-radius: 50%;
    font-size: .8125rem;
    font-weight: 700;
    color: var(--text-on-accent);
    background: var(--grad-brand);
}

.user-menu__label {
    max-width: 10rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.user-menu__caret {
    width: 14px;
    height: 14px;
    color: var(--text-muted);
    transition: transform .2s var(--ease);
}

.user-menu__trigger[aria-expanded="true"] .user-menu__caret { transform: rotate(180deg); }

.user-menu__panel {
    position: absolute;
    right: 0;
    top: calc(100% + .5rem);
    z-index: 40;
    width: 15rem;
    padding: var(--space-2);
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    animation: nav-drop .16s var(--ease-out);
}

.user-menu__panel[hidden] { display: none; }

.user-menu__head {
    padding: var(--space-3);
    border-bottom: 1px solid var(--line);
    margin-bottom: var(--space-2);
}

.user-menu__name {
    margin: 0;
    max-width: none;
    font-size: .875rem;
    font-weight: 650;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
}

.user-menu__email {
    margin: 2px 0 0;
    max-width: none;
    font-size: .75rem;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
}

.user-menu__role {
    display: inline-block;
    margin-top: var(--space-2);
    padding: .1rem .5rem;
    font-size: .625rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--accent-text);
    background: var(--accent-soft);
    border-radius: var(--radius-pill);
}

.user-menu__list { display: flex; flex-direction: column; }

.user-menu__list a {
    padding: .5rem .75rem;
    border-radius: var(--radius-sm);
    font-size: .875rem;
    color: var(--text-secondary);
    text-decoration: none;
}

.user-menu__list a:hover { background: var(--bg-inset); color: var(--text); }

.user-menu__signout {
    margin-top: var(--space-2);
    padding-top: var(--space-2);
    border-top: 1px solid var(--line);
}

/* Hamburger. Hidden until the breakpoint; the three bars morph into a cross so
   the open state is unambiguous without a second icon. */
.nav-toggle {
    display: none;
    place-items: center;
    width: 40px;
    height: 40px;
    flex: none;
    margin-left: auto;
    padding: 0;
    background: transparent;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    cursor: pointer;
}

.nav-toggle__box {
    position: relative;
    width: 18px;
    height: 12px;
}

.nav-toggle__bar {
    position: absolute;
    left: 0;
    width: 100%;
    height: 2px;
    border-radius: 2px;
    background: var(--text);
    transition: transform .25s var(--ease), opacity .15s var(--ease);
}

.nav-toggle__bar:nth-child(1) { top: 0; }
.nav-toggle__bar:nth-child(2) { top: 5px; }
.nav-toggle__bar:nth-child(3) { top: 10px; }

.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(1) { transform: translateY(5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }

@media (max-width: 960px) {
    :root { --header-h: 64px; }

    .nav-toggle { display: grid; }

    .site-header__inner { min-height: 64px; }

    .site-header__collapse {
        position: absolute;
        left: 0;
        right: 0;
        top: 100%;
        display: none;
        flex-direction: column;
        align-items: stretch;
        gap: var(--space-4);
        padding: var(--space-4) var(--space-6) var(--space-6);
        background: var(--bg);
        border-bottom: 1px solid var(--line);
        box-shadow: var(--shadow-lg);
    }

    .site-header__collapse.is-open {
        display: flex;
        animation: nav-drop .18s var(--ease-out);
    }

    .site-nav {
        flex-direction: column;
        align-items: stretch;
        gap: 2px;
        font-size: 1rem;
    }

    .site-nav a { padding: .7rem .75rem; }

    .site-nav a.is-current::after { left: .75rem; right: auto; width: 14px; bottom: .5rem; }

    .site-header__actions {
        flex-wrap: wrap;
        padding-top: var(--space-4);
        border-top: 1px solid var(--line);
    }

    .site-header__actions .btn,
    .site-header__actions .inline-form { flex: 1 1 auto; }
    .site-header__actions .inline-form .btn { width: 100%; }

    /* Inside the collapsed panel there is nothing to float over, so the menu
       becomes part of the flow rather than a dropdown on top of a dropdown. */
    .user-menu { flex: 1 1 100%; }
    .user-menu__trigger { width: 100%; justify-content: flex-start; }
    .user-menu__label { max-width: none; }
    .user-menu__caret { margin-left: auto; }

    .user-menu__panel {
        position: static;
        width: auto;
        margin-top: var(--space-2);
        box-shadow: none;
        animation: none;
    }
}

@keyframes nav-drop {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* --------------------------------------------------------------------------
   4. Buttons
   -------------------------------------------------------------------------- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: .625rem 1.15rem;
    font: inherit;
    font-size: .9375rem;
    font-weight: 570;
    line-height: 1.2;
    letter-spacing: -.005em;
    white-space: nowrap;
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    cursor: pointer;
    text-decoration: none;
    transition: background .18s var(--ease), border-color .18s var(--ease),
                color .18s var(--ease), box-shadow .18s var(--ease),
                transform .18s var(--ease);
}

.btn svg { width: 1.05em; height: 1.05em; flex: none; }

.btn:active { transform: translateY(1px); }

.btn--primary {
    background: var(--grad-brand);
    color: var(--text-on-accent);
    box-shadow: var(--shadow-accent);
}

.btn--primary:hover {
    color: var(--text-on-accent);
    box-shadow: 0 10px 30px var(--accent-glow);
    filter: brightness(1.06);
}

.btn--ghost {
    background: var(--surface);
    border-color: var(--line);
    color: var(--text);
}

.btn--ghost:hover {
    border-color: var(--line-strong);
    background: var(--bg-inset);
    color: var(--text);
}

/* Tinted, for a secondary action that still belongs to the brand. */
.btn--soft {
    background: var(--accent-soft);
    border-color: var(--accent-line);
    color: var(--accent-text);
}

.btn--soft:hover {
    background: var(--accent-softer);
    color: var(--accent-text);
}

/*
  The header pair. Slightly tighter than a page button, because the bar now
  carries four controls — switch, account, Pricing, Download — and at the full
  1.15rem of horizontal padding they crowded the navigation off the bar
  somewhere around 1080px.

  Below the mobile breakpoint the size resets: inside the collapsed panel these
  become full-width rows, where a small button is a small target.
*/
.btn--nav {
    padding: .5rem .85rem;
    font-size: .875rem;
}

@media (max-width: 960px) {
    .btn--nav { padding: .625rem 1.15rem; font-size: .9375rem; }
}

/* Chromeless, for header links that must not compete with the primary action. */
.btn--quiet {
    background: transparent;
    border-color: transparent;
    color: var(--text-secondary);
}

.btn--quiet:hover {
    background: var(--bg-inset);
    color: var(--text);
}

/* On a saturated panel, where the tokens above would vanish. */
.btn--invert {
    background: var(--p-white);
    color: var(--p-cyan-700);
}

.btn--invert:hover {
    background: var(--p-white);
    color: var(--p-cyan-ink);
    box-shadow: var(--shadow-lg);
}

.btn--outline-invert {
    background: transparent;
    border-color: rgba(255, 255, 255, .45);
    color: var(--p-white);
}

.btn--outline-invert:hover {
    background: rgba(255, 255, 255, .12);
    border-color: var(--p-white);
    color: var(--p-white);
}

.btn.is-disabled {
    opacity: .5;
    cursor: not-allowed;
    pointer-events: none;
}

/* --------------------------------------------------------------------------
   5. Alerts
   -------------------------------------------------------------------------- */

.alert {
    margin: var(--space-4) 0;
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    border: 1px solid transparent;
    max-width: none;
    font-size: .9375rem;
}

.alert--success {
    background: var(--success-bg);
    border-color: var(--success-line);
    color: var(--success-fg);
}

.alert--error {
    background: var(--danger-bg);
    border-color: var(--danger-line);
    color: var(--danger-fg);
}

/* --------------------------------------------------------------------------
   6. Hero
   -------------------------------------------------------------------------- */

.hero {
    position: relative;
    overflow: hidden;
    padding: var(--space-16) 0 var(--space-12);
    background: var(--grain), var(--grad-mesh), var(--bg);
}

/* A faint grid behind the hero. It reads as engineering rather than marketing,
   and it is the cheapest depth available — no image, no request. */
.hero::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image:
        linear-gradient(to right, var(--line) 1px, transparent 1px),
        linear-gradient(to bottom, var(--line) 1px, transparent 1px);
    background-size: 64px 64px;
    opacity: .5;
    mask-image: radial-gradient(70% 60% at 50% 25%, #000 25%, transparent 75%);
    -webkit-mask-image: radial-gradient(70% 60% at 50% 25%, #000 25%, transparent 75%);
    pointer-events: none;
}

.hero__inner {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    gap: var(--space-12);
    align-items: center;
}

.hero__copy { max-width: 34rem; }

.eyebrow {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    margin-bottom: var(--space-6);
    padding: .35rem .875rem .35rem .5rem;
    font-size: .8125rem;
    font-weight: 560;
    letter-spacing: .005em;
    color: var(--accent-text);
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
    border-radius: var(--radius-pill);
}

.eyebrow__tag {
    padding: .1rem .5rem;
    font-size: .6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--text-on-accent);
    background: var(--accent);
    border-radius: var(--radius-pill);
}

.hero__title {
    font-size: clamp(2.25rem, 5.2vw, 3.75rem);
    line-height: 1.05;
    letter-spacing: -.035em;
    margin-bottom: var(--space-6);
}

/* The one gradient on the page that lands on type. Cyan into violet, the same
   two accents the app uses, and wide enough that the middle of the phrase is
   still the accent rather than a muddy transition. */
.hero__title em {
    font-style: normal;
    background: var(--grad-duo);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    /* Safari drops the descenders of clipped text without this. */
    padding-bottom: .06em;
}

.hero__lede {
    font-size: clamp(1.0625rem, 1.4vw, 1.1875rem);
    color: var(--text-secondary);
    max-width: 46ch;
    margin-bottom: var(--space-8);
}

.hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-bottom: var(--space-6);
}

.hero__note {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
    margin: 0;
    font-size: .8125rem;
    color: var(--text-muted);
    max-width: none;
}

.hero__note span {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
}

.hero__note svg { width: 14px; height: 14px; color: var(--success-fg); flex: none; }

@media (max-width: 980px) {
    .hero__inner { grid-template-columns: minmax(0, 1fr); gap: var(--space-8); }
    .hero__copy { max-width: 40rem; }
}

/* --------------------------------------------------------------------------
   7. Sections, grid, cards
   -------------------------------------------------------------------------- */

.section {
    padding: var(--space-24) 0;
}

.section--muted {
    background: var(--bg-subtle);
    border-block: 1px solid var(--line);
}

.section__title {
    font-size: clamp(1.75rem, 3.4vw, 2.5rem);
    letter-spacing: -.03em;
    margin-bottom: var(--space-8);
}

/* Centred section header: kicker, title, one line of context. */
.section-head {
    max-width: 46rem;
    margin: 0 auto var(--space-12);
    text-align: center;
}

.section-head .section__title { margin-bottom: var(--space-4); }

.section-head__lede {
    margin: 0 auto;
    font-size: 1.0625rem;
    color: var(--text-secondary);
}

.kicker {
    display: block;
    margin-bottom: var(--space-3);
    font-size: .75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: var(--accent-text);
}

.grid {
    display: grid;
    gap: var(--space-6);
}

.grid--3 {
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

.card {
    padding: var(--space-6);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

.card__title {
    font-size: 1.0625rem;
    margin-bottom: var(--space-2);
}

.card__body {
    margin: 0;
    color: var(--text-secondary);
    font-size: .9375rem;
}

/* --------------------------------------------------------------------------
   8. Build status (temporary — replaced by the real site in Phase 11)
   -------------------------------------------------------------------------- */

.build-status__lede {
    color: var(--ink-500);
    margin-bottom: var(--space-8);
}

.phase-list {
    list-style: none;
    margin: 0 0 var(--space-8);
    padding: 0;
    display: grid;
    gap: var(--space-2);
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}

.phase-list__item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    background: var(--paper);
    border: 1px solid var(--ink-100);
    border-radius: var(--radius-md);
    font-size: .875rem;
    color: var(--ink-300);
}

.phase-list__item.is-done {
    color: var(--success-fg);
    border-color: var(--success-line);
    background: var(--success-bg);
}

.phase-list__num {
    display: grid;
    place-items: center;
    flex: none;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: var(--ink-100);
    color: var(--ink-500);
    font-size: .75rem;
    font-weight: 650;
}

.phase-list__item.is-done .phase-list__num {
    background: var(--success-fg);
    color: var(--bg);
}

.build-status__foot {
    font-size: .9375rem;
    color: var(--ink-500);
}

/* --------------------------------------------------------------------------
   8b. Forms and authentication
   -------------------------------------------------------------------------- */

.auth {
    display: grid;
    place-items: center;
    padding: var(--space-16) var(--space-6);
    min-height: 70vh;
    background: var(--grain), var(--grad-mesh), var(--bg-subtle);
}

/* Used when the card sits inside an already-framed page (the account area)
   rather than standing alone as the whole screen. */
.auth--inline {
    min-height: 0;
    padding: var(--space-12) var(--space-6);
    background: none;
}

/* --------------------------------------------------------------------------
   Authentication screens — one column, read top to bottom

   These used to be a two-column split: the form in the left half, a full-height
   brand panel in the right. It only worked at one width. Below 900px the panel
   was hidden outright, so the answer to "what am I signing into?" was given
   only to people on large monitors — and on those monitors the form sat
   off-centre in its own half rather than where the eye lands.

   So the page runs down the middle now: mark, heading, the form in a raised
   card, and underneath it the reassurance the panel used to carry. That is the
   order somebody reads in, and it is the same order at every width.
   -------------------------------------------------------------------------- */

body.page-auth .promo-bar { display: none; }

.auth-stack {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    padding: var(--space-16) var(--space-6) var(--space-24);
    background: var(--grain), var(--grad-mesh), var(--bg-subtle);
}

/* The marketing hero's grid, masked to an ellipse so it fades out before it
   reaches an edge — a grid that runs into the header reads as a table. */
.auth-stack::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background-image:
        linear-gradient(to right, var(--line) 1px, transparent 1px),
        linear-gradient(to bottom, var(--line) 1px, transparent 1px);
    background-size: 56px 56px;
    mask-image: radial-gradient(70% 60% at 50% 0%, #000 8%, transparent 78%);
    -webkit-mask-image: radial-gradient(70% 60% at 50% 0%, #000 8%, transparent 78%);
    pointer-events: none;
}

.auth-stack__inner {
    position: relative;
    width: 100%;
    max-width: 30rem;
    margin-inline: auto;
    text-align: center;
}

/* Wider only where the form itself is wider — registration sets the password
   and its confirmation side by side. */
.auth-stack--wide .auth-stack__inner { max-width: 34rem; }

.auth-stack__brand {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    margin-bottom: var(--space-6);
    padding: .35rem .9rem .35rem .4rem;
    border: 1px solid var(--line);
    border-radius: var(--radius-pill);
    background: var(--surface);
    box-shadow: var(--shadow-sm);
    font-size: .8125rem;
    font-weight: 640;
    letter-spacing: -.01em;
    color: var(--text);
    text-decoration: none;
}

.auth-stack__brand:hover { color: var(--text); border-color: var(--accent-line); }

.auth-stack__brand img { width: 24px; height: 24px; border-radius: 7px; }

.auth-stack__title {
    margin: 0 0 var(--space-3);
    font-size: clamp(1.75rem, 4.5vw, 2.5rem);
    letter-spacing: -.038em;
}

.auth-stack__lede {
    max-width: 44ch;
    margin: 0 auto var(--space-8);
    font-size: 1rem;
    color: var(--text-secondary);
}

.auth-stack__lede strong { color: var(--text); font-weight: 620; }

/* The card holding the form. Left-aligned inside the centred column: a label
   sitting over the middle of its own input is unreadable at speed. */
.auth-card {
    padding: var(--space-8);
    text-align: left;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-lg);
}

.auth-card__foot {
    margin: var(--space-6) 0 0;
    padding-top: var(--space-6);
    border-top: 1px solid var(--line);
    font-size: .875rem;
    text-align: center;
    color: var(--text-secondary);
    max-width: none;
}

.auth-stack__legal {
    max-width: 48ch;
    margin: var(--space-6) auto 0;
    font-size: .75rem;
    line-height: 1.6;
    color: var(--text-muted);
}

/* The wide half of the column: everything below the card, which has no reason
   to be as narrow as a form. */
.auth-stack__foot {
    position: relative;
    width: 100%;
    max-width: 58rem;
    margin: var(--space-12) auto 0;
}

/*
  What the brand panel used to say, as a row under the card.

  Three short claims rather than a paragraph: this is the last thing on the
  page and it is read at a glance or not at all.
*/
.auth-points {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: var(--space-6);
    margin: 0;
    padding: 0;
    list-style: none;
    text-align: left;
}

.auth-points li {
    display: grid;
    grid-template-columns: 20px minmax(0, 1fr);
    gap: var(--space-3);
    align-items: start;
    font-size: .875rem;
    line-height: 1.55;
    color: var(--text-secondary);
}

.auth-points svg { width: 20px; height: 20px; color: var(--accent); margin-top: 1px; }

/* The product's own numbers along the foot, where the split screen used to end. */
.auth-figures {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-6) var(--space-12);
    margin: var(--space-8) 0 0;
    padding-top: var(--space-8);
    border-top: 1px solid var(--line);
    list-style: none;
}

.auth-figures li { font-size: .75rem; color: var(--text-muted); text-align: center; }

.auth-figures strong {
    display: block;
    font-size: 1.375rem;
    font-weight: 700;
    letter-spacing: -.03em;
    color: var(--text);
}

@media (max-width: 560px) {
    .auth-stack { padding: var(--space-12) var(--space-4) var(--space-16); }
    .auth-card { padding: var(--space-6); }
}


.auth__card {
    width: 100%;
    max-width: 27rem;
    padding: var(--space-8);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
}

.auth__title {
    font-size: 1.5rem;
    margin-bottom: var(--space-2);
}

.auth__lede {
    color: var(--text-secondary);
    font-size: .9375rem;
    margin-bottom: var(--space-6);
}

.auth__alt {
    margin: var(--space-6) 0 0;
    padding-top: var(--space-4);
    border-top: 1px solid var(--line);
    font-size: .875rem;
    color: var(--text-secondary);
    text-align: center;
}

.field {
    margin-bottom: var(--space-4);
}

.field__label {
    display: block;
    margin-bottom: var(--space-1);
    font-size: .875rem;
    font-weight: 550;
    color: var(--ink-700);
}

.field__label-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-2);
}

.field__link {
    font-size: .8125rem;
}

.field__input,
.field__select,
.field__textarea {
    width: 100%;
    padding: .6rem .75rem;
    font: inherit;
    font-size: .9375rem;
    color: var(--ink-900);
    background: var(--paper);
    border: 1px solid var(--ink-300);
    border-radius: var(--radius-md);
    transition: border-color .15s ease, box-shadow .15s ease;
}

.field__input:focus,
.field__select:focus,
.field__textarea:focus {
    outline: none;
    border-color: var(--brand-500);
    box-shadow: 0 0 0 3px var(--brand-100);
}

.field__input.is-invalid {
    border-color: var(--err-600);
}

.field__input.is-invalid:focus {
    box-shadow: 0 0 0 3px var(--err-100);
}

.field__error {
    margin: var(--space-1) 0 0;
    font-size: .8125rem;
    color: var(--err-600);
    max-width: none;
}

.field__hint {
    margin: var(--space-1) 0 0;
    font-size: .8125rem;
    color: var(--ink-300);
    max-width: none;
}

.checkbox {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin-bottom: var(--space-6);
    font-size: .875rem;
    color: var(--ink-500);
    cursor: pointer;
}

.checkbox input {
    margin-top: .2em;
    flex: none;
    accent-color: var(--brand-600);
}

.checkbox.is-invalid span {
    color: var(--err-600);
}

.btn--block {
    width: 100%;
}

.inline-form {
    display: inline;
}

.btn--small {
    padding: .35rem .75rem;
    font-size: .8125rem;
}

/* Impersonation banner — deliberately loud, because forgetting you are wearing
   someone else's account is how mistakes get made. */
/* Fixed amber rather than the themed token: this bar must look identical and
   alarming in both themes, and the dark-theme amber is far too light to carry
   white text. */
.impersonation-bar {
    background: var(--p-amber-600);
    color: var(--p-white);
    position: relative;
    z-index: 30;
}

.impersonation-bar__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding-block: var(--space-2);
}

.impersonation-bar__text {
    font-size: .875rem;
}

.impersonation-bar .btn--ghost {
    border-color: rgba(255, 255, 255, .5);
    color: #fff;
    background: transparent;
}

.impersonation-bar .btn--ghost:hover {
    background: rgba(255, 255, 255, .12);
    border-color: #fff;
    color: #fff;
}

/* --------------------------------------------------------------------------
   8c. Notices, detail lists, page headers
   -------------------------------------------------------------------------- */

.notice {
    margin: var(--space-6) 0;
    padding: var(--space-4);
    border-radius: var(--radius-md);
    border: 1px solid var(--ink-100);
    background: var(--ink-50);
}

.notice--warn {
    background: var(--warning-bg);
    border-color: var(--warning-line);
}

.notice--dev {
    background: var(--accent-soft);
    border-color: var(--accent-line);
}

.notice__title {
    margin: 0 0 var(--space-1);
    font-weight: 600;
    font-size: .9375rem;
    color: var(--ink-900);
    max-width: none;
}

.notice__body {
    margin: 0 0 var(--space-3);
    font-size: .875rem;
    color: var(--ink-500);
    max-width: none;
}

.notice__body:last-child {
    margin-bottom: 0;
}

.badge {
    display: inline-block;
    padding: .15rem .55rem;
    font-size: .75rem;
    font-weight: 600;
    border-radius: 999px;
    border: 1px solid transparent;
    white-space: nowrap;
}

.badge--ok {
    background: var(--success-bg);
    border-color: var(--success-line);
    color: var(--success-fg);
}

.badge--warn {
    background: var(--warning-bg);
    border-color: var(--warning-line);
    color: var(--warning-fg);
}

.page-head {
    margin-bottom: var(--space-8);
}

.page-head__title {
    font-size: clamp(1.5rem, 4vw, 2rem);
    margin-bottom: var(--space-2);
}

.page-head__lede {
    color: var(--ink-500);
    margin: 0;
}

.detail-list {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--space-2) var(--space-4);
    margin: 0;
    font-size: .875rem;
}

.detail-list dt {
    color: var(--ink-300);
}

.detail-list dd {
    margin: 0;
    color: var(--ink-700);
}

.dashboard__admin-link {
    margin-top: var(--space-8);
    padding: var(--space-4);
    background: var(--ink-50);
    border: 1px solid var(--ink-100);
    border-radius: var(--radius-md);
    font-size: .875rem;
    max-width: none;
}

/* --------------------------------------------------------------------------
   8d. Pricing
   -------------------------------------------------------------------------- */

.pricing-head {
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: var(--space-12);
}

.pricing-head__title {
    font-size: clamp(1.75rem, 5vw, 2.75rem);
    margin-bottom: var(--space-4);
}

.pricing-head__lede {
    color: var(--ink-500);
    max-width: 56ch;
    margin-bottom: var(--space-6);
}

.currency-switch {
    display: inline-flex;
    padding: 3px;
    background: var(--ink-50);
    border: 1px solid var(--ink-100);
    border-radius: 999px;
}

.currency-switch__option {
    padding: .35rem 1rem;
    font-size: .875rem;
    font-weight: 550;
    color: var(--ink-500);
    text-decoration: none;
    border-radius: 999px;
}

.currency-switch__option:hover {
    color: var(--ink-900);
}

.currency-switch__option.is-active {
    background: var(--paper);
    color: var(--brand-600);
    box-shadow: var(--shadow-sm);
}

.pricing-grid {
    display: grid;
    /* 250, not 275. The catalogue is four tiers and the container's inner width
       is 1132px: at 275 the fourth card needed 1172 and dropped onto a row of
       its own, which reads as an afterthought rather than as the top tier. */
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: var(--space-6);
    align-items: start;
}

.plan-card {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: var(--space-8) var(--space-6);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    transition: border-color .2s var(--ease), box-shadow .2s var(--ease),
                transform .2s var(--ease);
}

.plan-card:hover {
    border-color: var(--line-strong);
    box-shadow: var(--shadow-md);
    transform: translateY(-2px);
}

.plan-card--featured {
    border-color: var(--accent);
    box-shadow: var(--shadow-lg);
}

/* The featured card lifts a little on its own so the flag has somewhere to sit
   without overlapping the card above it on a narrow screen. */
@media (min-width: 900px) {
    .plan-card--featured { transform: translateY(-8px); }
    .plan-card--featured:hover { transform: translateY(-12px); }
}

.plan-card__flag {
    position: absolute;
    top: -.8rem;
    left: 50%;
    transform: translateX(-50%);
    padding: .25rem .875rem;
    font-size: .6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--text-on-accent);
    background: var(--grad-brand);
    box-shadow: var(--shadow-accent);
    border-radius: var(--radius-pill);
    white-space: nowrap;
}

.plan-card__name {
    font-size: 1.25rem;
    margin-bottom: var(--space-1);
}

.plan-card__tagline {
    margin: 0 0 var(--space-4);
    font-size: .875rem;
    color: var(--ink-500);
}

.plan-card__price {
    margin: 0 0 var(--space-4);
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-2);
}

.plan-card__was {
    font-size: 1rem;
    color: var(--ink-300);
    text-decoration: line-through;
}

.plan-card__amount {
    font-size: 2.25rem;
    font-weight: 700;
    letter-spacing: -.03em;
    color: var(--ink-900);
    line-height: 1;
}

.plan-card__period {
    font-size: .875rem;
    color: var(--ink-500);
}

.plan-card__meta {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
    margin: 0 0 var(--space-4);
    padding: var(--space-3) 0;
    border-block: 1px solid var(--ink-100);
    font-size: .8125rem;
    color: var(--ink-500);
}

.plan-card__meta strong {
    color: var(--ink-900);
}

.plan-card__features {
    list-style: none;
    margin: 0 0 var(--space-6);
    padding: 0;
    display: grid;
    gap: var(--space-2);
    font-size: .9375rem;
}

.plan-card__features li {
    position: relative;
    padding-left: 1.5rem;
    color: var(--ink-700);
}

.plan-card__features li::before {
    content: "";
    position: absolute;
    left: 0;
    top: .45em;
    width: .85rem;
    height: .45rem;
    border-left: 2px solid var(--ok-600);
    border-bottom: 2px solid var(--ok-600);
    transform: rotate(-45deg);
}

.plan-card__description {
    margin: 0 0 var(--space-6);
    font-size: .875rem;
    color: var(--ink-500);
}

/* Pin the call to action to the bottom so cards of differing height align. */
.plan-card .btn {
    margin-top: auto;
}

.pricing-note {
    margin: var(--space-8) auto 0;
    text-align: center;
    font-size: .8125rem;
    color: var(--ink-300);
    max-width: 60ch;
}

.faq {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: var(--space-6);
}

.faq__q {
    font-size: 1rem;
    margin-bottom: var(--space-2);
}

.faq__a {
    margin: 0;
    font-size: .9375rem;
    color: var(--text-secondary);
}

/* Accordion variant. <details> gives the open/close behaviour for free, which
   is the whole reason it is used here — no state to script, and it stays
   operable with JS off. */
.faq--accordion {
    display: block;
    max-width: 52rem;
    margin-inline: auto;
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    background: var(--surface);
    overflow: hidden;
}

.faq__item--toggle {
    border-bottom: 1px solid var(--line);
}

.faq__item--toggle:last-child { border-bottom: 0; }

.faq__item--toggle > summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-4) var(--space-6);
    font-size: 1rem;
    font-weight: 600;
    color: var(--text);
    cursor: pointer;
    list-style: none;
    transition: background-color .15s var(--ease);
}

.faq__item--toggle > summary::-webkit-details-marker { display: none; }
.faq__item--toggle > summary:hover { background: var(--bg-inset); }

.faq__sign {
    position: relative;
    width: 14px;
    height: 14px;
    flex: none;
    color: var(--text-muted);
}

.faq__sign::before,
.faq__sign::after {
    content: "";
    position: absolute;
    inset: 50% 0 auto;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
    transition: transform .2s var(--ease);
}

.faq__sign::after { transform: rotate(90deg); }

.faq__item--toggle[open] > summary { color: var(--accent-text); }
.faq__item--toggle[open] .faq__sign { color: var(--accent); }
.faq__item--toggle[open] .faq__sign::after { transform: rotate(0deg); }

.faq__item--toggle > .faq__a {
    padding: 0 var(--space-6) var(--space-6);
    max-width: 62ch;
}

/* --------------------------------------------------------------------------
   9. Error pages
   -------------------------------------------------------------------------- */

.error-page {
    padding: var(--space-16) 0;
    min-height: 60vh;
    display: grid;
    place-items: center;
}

.error-page__inner {
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.error-page__code {
    font-size: clamp(3rem, 10vw, 5rem);
    font-weight: 700;
    line-height: 1;
    letter-spacing: -.04em;
    color: var(--ink-100);
    margin-bottom: var(--space-4);
}

.error-page__title {
    font-size: clamp(1.375rem, 4vw, 2rem);
}

.error-page__body {
    color: var(--ink-500);
    margin-bottom: var(--space-6);
}

.error-page__actions {
    margin-bottom: var(--space-8);
}

.error-page__debug {
    max-width: 100%;
    width: min(100%, 900px);
    overflow-x: auto;
    text-align: left;
    padding: var(--space-4);
    background: var(--p-n-950);
    color: var(--p-n-200);
    border-radius: var(--radius-md);
    font-family: var(--font-mono);
    font-size: .8125rem;
    line-height: 1.5;
}

.error-page__debug pre {
    margin: var(--space-3) 0 0;
    white-space: pre;
}

.error-page__debug-head {
    margin: 0;
    max-width: none;
    color: var(--p-red-400);
}

.error-page__debug-file {
    margin: var(--space-2) 0 0;
    max-width: none;
    color: var(--ink-300);
}

/* --------------------------------------------------------------------------
   10. Footer
   -------------------------------------------------------------------------- */

.site-footer {
    border-top: 1px solid var(--line);
    padding: var(--space-8) 0 0;
    background: var(--bg-subtle);
}

.site-footer__inner {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-6);
    justify-content: space-between;
    align-items: center;
}

.site-footer__copy,
.site-footer__legal {
    margin: 0;
    font-size: .8125rem;
    color: var(--ink-300);
    max-width: none;
}

/* --------------------------------------------------------------------------
   11. Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 720px) {
    .container { padding-inline: var(--space-4); }

    .hero {
        padding-top: var(--space-12);
    }

    .section {
        padding: var(--space-16) 0;
    }

    .cta-band,
    .cta-band--large { padding: var(--space-6); }

    .cta-band__actions .btn { flex: 1 1 auto; }
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: .01ms !important;
        transition-duration: .01ms !important;
    }
}

/* Uploaded logo, replacing the built-in wordmark when one is set. */
.brand__logo {
    display: block;
    max-height: 32px;
    max-width: 180px;
}

/* --------------------------------------------------------------------------
   Accepted payment methods
   Rendered from the gateways that accept the currency on screen, so the list
   changes with the currency switcher rather than being decorative.
   -------------------------------------------------------------------------- */

.payment-methods {
    margin: var(--space-12) auto 0;
    max-width: 900px;
    text-align: center;
}

.payment-methods__title {
    margin: 0 0 var(--space-4);
    font-size: .8125rem;
    font-weight: 650;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--ink-500);
}

.payment-methods__list {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-3);
    margin: 0;
    padding: 0;
    list-style: none;
}

.payment-method {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-1);
    min-width: 150px;
    padding: var(--space-3) var(--space-4);
    background: var(--paper);
    border: 1px solid var(--ink-100);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
}

.payment-method__logo {
    width: auto;
    max-width: 80px;
    max-height: 32px;
    object-fit: contain;
}

.payment-method__name {
    font-size: .875rem;
    font-weight: 600;
    color: var(--ink-900);
}

.payment-method__note {
    font-size: .75rem;
    color: var(--ink-500);
}

.payment-methods__note {
    margin: var(--space-4) auto 0;
    max-width: 60ch;
    font-size: .8125rem;
    color: var(--ink-300);
}

/* ==========================================================================
   Checkout, orders and receipts
   ========================================================================== */

.container--narrow { max-width: 860px; }

.page-title {
    margin: 0 0 var(--space-6);
    font-size: clamp(1.6rem, 3vw, 2.1rem);
    line-height: 1.2;
    letter-spacing: -.01em;
    color: var(--ink-900);
}

.page-head .page-title { margin-bottom: 0; }

.breadcrumb {
    margin: 0 0 var(--space-4);
    font-size: .8125rem;
    color: var(--text-muted);
}

.breadcrumb a { color: var(--text-secondary); text-decoration: none; }
.breadcrumb a:hover { color: var(--accent-text); }

/* Status badges. The public site had only two; orders need the full set. */
.badge--info    { background: var(--brand-100); color: var(--brand-600); }
.badge--err     { background: var(--err-100);   color: var(--err-600); }
.badge--pending { background: var(--ink-50);    color: var(--ink-500); }

.notice--info  { border-left-color: var(--brand-500); background: var(--brand-100); }
.notice--error { border-left-color: var(--err-600);   background: var(--err-100); }

.notice__list { margin: var(--space-2) 0 0; padding-left: 1.1rem; font-size: .875rem; }

.field__hint--ok { color: var(--ok-600); }

.field-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: var(--space-4);
}

/* --------------------------------------------------------------- Checkout */

.checkout {
    display: grid;
    grid-template-columns: minmax(0, 1.6fr) minmax(280px, 1fr);
    gap: var(--space-8);
    align-items: start;
}

/* The total should not scroll away while the payment methods are being read. */
@media (min-width: 821px) {
    .checkout__summary { position: sticky; top: calc(var(--header-h) + var(--space-4)); }
}

.checkout__form {
    padding: var(--space-8);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

@media (max-width: 820px) {
    .checkout { grid-template-columns: minmax(0, 1fr); }
    /* Summary first on a phone: what you are paying matters more than how. */
    .checkout__summary { order: -1; }
}

.checkout__block {
    margin: 0 0 var(--space-6);
    padding: 0;
    border: 0;
}

.checkout__legend {
    padding: 0;
    margin: 0 0 var(--space-3);
    font-size: .8125rem;
    font-weight: 650;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--ink-500);
}

.checkout__coupon { max-width: 320px; }

.checkout__legal {
    margin: var(--space-4) 0 0;
    font-size: .75rem;
    color: var(--ink-300);
}

.checkout__summary {
    position: sticky;
    top: var(--space-4);
    padding: var(--space-6);
    background: var(--paper);
    border: 1px solid var(--ink-100);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

.checkout__summary-title {
    margin: 0 0 var(--space-4);
    font-size: .75rem;
    font-weight: 650;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--ink-300);
}

.checkout__plan { margin: 0; font-size: 1.05rem; font-weight: 650; color: var(--ink-900); }
.checkout__tagline { margin: var(--space-1) 0 0; font-size: .8125rem; color: var(--ink-500); }

.checkout__facts {
    margin: var(--space-3) 0 var(--space-4);
    padding: 0;
    list-style: none;
    font-size: .8125rem;
    color: var(--ink-500);
}

.checkout__facts li { padding: 2px 0; }

.checkout__totals { margin: 0; padding-top: var(--space-3); border-top: 1px solid var(--ink-100); }

.checkout__line {
    display: flex;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-2) 0;
    font-size: .9375rem;
}

.checkout__line dt { color: var(--ink-500); }
.checkout__line dd { margin: 0; font-variant-numeric: tabular-nums; }
.checkout__line--discount dd { color: var(--ok-600); }

.checkout__line--total {
    margin-top: var(--space-2);
    padding-top: var(--space-3);
    border-top: 1px solid var(--ink-100);
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--ink-900);
}

.checkout__note {
    margin: var(--space-4) 0 0;
    font-size: .75rem;
    line-height: 1.5;
    color: var(--ink-300);
}

/* ------------------------------------------------------- Method selection */

.method {
    display: block;
    margin-bottom: var(--space-3);
    padding: var(--space-4) var(--space-6);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: border-color .15s var(--ease), box-shadow .15s var(--ease),
                background-color .15s var(--ease);
}

.method:hover { border-color: var(--line-strong); background: var(--bg-inset); }

.method:has(input:checked) {
    border-color: var(--accent);
    background: var(--accent-soft);
    box-shadow: 0 0 0 3px var(--ring);
}

.method:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }

.method input { accent-color: var(--accent); }

.method input { margin-right: var(--space-3); }

.method__body { display: inline-block; vertical-align: top; width: calc(100% - 2rem); }

.method__head { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.method__logo { max-width: 72px; max-height: 28px; width: auto; object-fit: contain; }
.method__name { font-weight: 650; color: var(--ink-900); }

.method__note {
    display: block;
    margin-top: var(--space-1);
    font-size: .8125rem;
    line-height: 1.5;
    color: var(--ink-500);
}

/* --------------------------------------------------------- Paying offline */

.pay-summary {
    display: grid;
    gap: var(--space-3);
    padding: var(--space-8);
    margin-bottom: var(--space-6);
    color: var(--text-on-accent);
    background: var(--grad-brand);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
}

.pay-summary .pay-summary__label,
.pay-summary .pay-summary__hint { color: var(--on-accent-muted); }
.pay-summary .pay-summary__amount { color: var(--text-on-accent); }

.pay-summary .pay-summary__reference {
    color: var(--text-on-accent);
    background: var(--on-accent-fill);
    border-color: var(--on-accent-line);
}

.pay-summary__row { display: flex; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap; }
.pay-summary__label { font-size: .875rem; color: var(--ink-700); }

.pay-summary__amount {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--ink-900);
    font-variant-numeric: tabular-nums;
}

.pay-summary__reference {
    padding: .15rem .6rem;
    font-family: var(--font-mono);
    font-size: 1.05rem;
    font-weight: 650;
    color: var(--ink-900);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    user-select: all;
}

.pay-summary__hint { margin: 0; font-size: .8125rem; color: var(--ink-700); }

.pay-steps { margin: 0 0 0 var(--space-6); padding: 0; list-style: none; counter-reset: pay-step; }

@media (max-width: 720px) { .pay-steps { margin-left: 0; } }

.pay-step {
    position: relative;
    margin-bottom: var(--space-6);
    padding: var(--space-8);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    counter-increment: pay-step;
}

/* The number is drawn rather than left to the list marker, so it can sit on the
   card's edge instead of outside it. */
.pay-step::before {
    content: counter(pay-step);
    position: absolute;
    top: var(--space-8);
    left: calc(var(--space-8) * -1 + .25rem);
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    font-size: .875rem;
    font-weight: 700;
    color: var(--text-on-accent);
    background: var(--grad-brand);
    box-shadow: var(--shadow-accent);
}

@media (max-width: 720px) {
    .pay-step { padding: var(--space-6); }
    .pay-step::before { position: static; margin-bottom: var(--space-4); }
}

.pay-step__title { margin: 0 0 var(--space-3); font-size: 1.15rem; color: var(--text); }
.pay-step__lede { margin: 0 0 var(--space-4); font-size: .9375rem; color: var(--text-secondary); }
.pay-step__logo { max-height: 34px; width: auto; margin-bottom: var(--space-4); }
.pay-step__instructions { margin: 0 0 var(--space-4); line-height: 1.7; }

.account-details {
    margin: 0 0 var(--space-4);
    padding: var(--space-4);
    background: var(--ink-50);
    border: 1px solid var(--ink-100);
    border-radius: var(--radius-md);
}

.account-details__title {
    margin: 0 0 var(--space-2);
    font-size: .75rem;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--ink-300);
}

.account-details__body {
    margin: 0;
    font-family: var(--font-mono);
    font-size: .875rem;
    line-height: 1.7;
    white-space: pre-wrap;
    word-break: break-word;
    user-select: all;
}

.pay-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-4);
    flex-wrap: wrap;
    font-size: .875rem;
}

/* ----------------------------------------------------------- Outcome page */

.outcome {
    max-width: 640px;
    margin: 0 auto;
    padding: var(--space-12) var(--space-8);
    text-align: center;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-lg);
}

.outcome--ok { border-top: 4px solid var(--success-fg); }
.outcome--problem { border-top: 4px solid var(--warning-fg); }

/* Result badge above the headline: a large tick or exclamation, drawn from the
   status colours so the page reads before it is read. */
.outcome__mark {
    display: grid;
    place-items: center;
    width: 64px;
    height: 64px;
    margin: 0 auto var(--space-6);
    border-radius: 50%;
    color: var(--text-secondary);
    background: var(--bg-inset);
}

.outcome__mark svg { width: 32px; height: 32px; }
.outcome--ok .outcome__mark { color: var(--success-fg); background: var(--success-bg); }
.outcome--problem .outcome__mark { color: var(--warning-fg); background: var(--warning-bg); }

.outcome__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-3); }

.outcome__title { margin: 0 0 var(--space-3); font-size: 1.6rem; color: var(--ink-900); }
.outcome__lede { margin: 0 0 var(--space-4); color: var(--ink-700); }
.outcome__note { margin: 0 0 var(--space-4); font-size: .875rem; color: var(--ink-500); }
.outcome__status { margin: 0 0 var(--space-6); }

.outcome__actions {
    display: flex;
    gap: var(--space-3);
    justify-content: center;
    flex-wrap: wrap;
}

/* ---------------------------------------------------------- Order history */

.empty-state {
    padding: var(--space-16) var(--space-6);
    text-align: center;
    background: var(--surface);
    border: 1px dashed var(--line-strong);
    border-radius: var(--radius-lg);
}

.empty-state__title { margin: 0 0 var(--space-2); font-size: 1.15rem; color: var(--text); }
.empty-state__body { margin: 0 auto var(--space-6); color: var(--text-secondary); max-width: 42ch; }

.order-list { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-3); }

.order-card {
    display: grid;
    grid-template-columns: minmax(0, 2fr) auto auto;
    gap: var(--space-4);
    align-items: center;
    padding: var(--space-4) var(--space-6);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    transition: border-color .2s var(--ease), box-shadow .2s var(--ease);
}

.order-card:hover { border-color: var(--line-strong); box-shadow: var(--shadow-sm); }

@media (max-width: 700px) {
    .order-card { grid-template-columns: minmax(0, 1fr); }
    .order-card__side { text-align: left; }
}

.order-card__number { margin: 0; font-family: var(--font-mono); font-size: .9375rem; }
.order-card__plan { margin: var(--space-1) 0 0; font-weight: 650; color: var(--ink-900); }
.order-card__meta { margin: var(--space-1) 0 0; font-size: .8125rem; color: var(--ink-300); }
.order-card__side { text-align: right; }

.order-card__amount {
    margin: 0 0 var(--space-1);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--ink-900);
}

.order-card__actions { display: flex; gap: var(--space-2); flex-wrap: wrap; }

.order-status-blurb { margin: 0 0 var(--space-6); color: var(--ink-500); }

.order-actions {
    display: flex;
    gap: var(--space-3);
    flex-wrap: wrap;
    align-items: center;
    margin-top: var(--space-6);
}

.panel-card {
    margin-bottom: var(--space-6);
    padding: var(--space-6);
    background: var(--paper);
    border: 1px solid var(--ink-100);
    border-radius: var(--radius-lg);
}

.panel-card__title { margin: 0 0 var(--space-4); font-size: 1.05rem; color: var(--ink-900); }

.detail-grid { margin: 0 0 var(--space-4); display: grid; gap: var(--space-3); }
.detail-grid > div { display: flex; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap; }
.detail-grid dt { font-size: .875rem; color: var(--ink-500); }
.detail-grid dd { margin: 0; font-size: .875rem; text-align: right; }

.proof {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 160px;
    gap: var(--space-4);
    align-items: start;
    padding: var(--space-4) 0;
    border-top: 1px solid var(--ink-100);
}

.proof:first-of-type { border-top: 0; padding-top: 0; }

@media (max-width: 600px) { .proof { grid-template-columns: minmax(0, 1fr); } }

.proof__meta p { margin: 0 0 var(--space-1); font-size: .875rem; }
.proof__submitted { color: var(--ink-500); }

.proof__thumb { display: block; border-radius: var(--radius-md); overflow: hidden; border: 1px solid var(--ink-100); }
.proof__thumb img { display: block; width: 100%; height: auto; }

/* ------------------------------------------------------------- Pagination */

.pagination {
    display: flex;
    gap: var(--space-2);
    justify-content: center;
    margin-top: var(--space-8);
}

.pagination__link {
    padding: .4rem .75rem;
    font-size: .875rem;
    color: var(--ink-500);
    background: var(--paper);
    border: 1px solid var(--ink-100);
    border-radius: var(--radius-sm);
    text-decoration: none;
}

.pagination__link:hover { border-color: var(--brand-500); color: var(--brand-600); }

.pagination__link.is-current {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--text-on-accent);
    font-weight: 650;
}

.pagination__gap { padding: .4rem .25rem; color: var(--ink-300); }

/* ==========================================================================
   Licence cards and devices

   One card per licence, in three bands: who it is (plan and state), what it is
   (the key), and where it runs (the devices). The key gets the most weight on
   the page because copying it is the single most common reason anybody opens
   this screen.
   ========================================================================== */

.licence-list { display: grid; gap: var(--space-8); }

.licence-card {
    position: relative;
    overflow: hidden;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-md);
}

/* State along the top edge, so a stack of licences sorts itself at a glance.
   Never the only carrier — the badges beside the plan name say it in words. */
.licence-card::before {
    content: "";
    position: absolute;
    inset: 0 0 auto;
    height: 3px;
    background: var(--grad-duo);
}

.licence-card--inactive { border-color: var(--warning-line); }
.licence-card--inactive::before { background: linear-gradient(90deg, var(--warning-fg), var(--p-amber-400)); }

.licence-card--revoked { border-color: var(--danger-line); }
.licence-card--revoked::before { background: linear-gradient(90deg, var(--danger-fg), var(--p-red-600)); }

.licence-card__head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-4);
    flex-wrap: wrap;
    padding: var(--space-6);
    background: var(--bg-subtle);
    border-bottom: 1px solid var(--line);
}

.licence-card__plan {
    margin: 0 0 var(--space-2);
    font-size: 1.25rem;
    letter-spacing: -.02em;
    color: var(--text);
}

.licence-card__status { margin: 0; display: flex; gap: var(--space-2); flex-wrap: wrap; }

.licence-card__body { padding: var(--space-6); }

.licence-card__note {
    display: flex;
    gap: var(--space-3);
    margin: 0 0 var(--space-6);
    padding: var(--space-4);
    font-size: .875rem;
    line-height: 1.55;
    color: var(--text-secondary);
    background: var(--warning-bg);
    border: 1px solid var(--warning-line);
    border-radius: var(--radius-lg);
    max-width: none;
}

.licence-card__note svg { width: 18px; height: 18px; flex: none; color: var(--warning-fg); }

/*
  The key.

  Big, monospaced, selectable, and one press from the clipboard. The label
  above it exists because the string on its own is unidentifiable to somebody
  who has landed here from an email and is looking for "the licence key".
*/
.licence-key-row {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    flex-wrap: wrap;
    padding: var(--space-4) var(--space-6);
    background: var(--bg-inset);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
}

.licence-key-row__label {
    display: block;
    margin-bottom: var(--space-1);
    font-size: .6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .11em;
    color: var(--text-muted);
}

.licence-key-row > div { flex: 1 1 16rem; min-width: 0; }

.licence-key-value {
    display: block;
    font-family: var(--font-mono);
    font-size: 1.1875rem;
    font-weight: 700;
    letter-spacing: .1em;
    line-height: 1.3;
    color: var(--text);
    word-break: break-all;
    user-select: all;
}

.btn.is-copied {
    background: var(--success-bg);
    border-color: var(--success-line);
    color: var(--success-fg);
}

.licence-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: var(--space-4);
    margin: var(--space-6) 0 0;
}

.licence-facts > div {
    padding: var(--space-4);
    background: var(--bg-subtle);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
}

.licence-facts dt {
    margin-bottom: var(--space-1);
    font-size: .6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .09em;
    color: var(--text-muted);
}

.licence-facts dd { margin: 0; font-size: .9375rem; font-weight: 640; color: var(--text); }
.licence-facts .muted { font-weight: 400; color: var(--text-muted); }

/* ---------------------------------------------------------------- Devices */

.devices {
    padding: var(--space-6);
    border-top: 1px solid var(--line);
    background: var(--bg-subtle);
}

.devices__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
    margin-bottom: var(--space-4);
}

.devices__title {
    margin: 0;
    font-size: .6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .1em;
    color: var(--text-muted);
}

/* Slots as dots: filled for a machine in use, hollow for one still free. It is
   the same number the facts strip prints, in the form people check first. */
.devices__slots { display: flex; gap: 5px; align-items: center; }

.devices__slots i {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    border: 1px solid var(--line-strong);
}

.devices__slots i.is-used { background: var(--accent); border-color: var(--accent); }

.devices__empty {
    margin: 0;
    padding: var(--space-6);
    text-align: center;
    font-size: .875rem;
    color: var(--text-muted);
    background: var(--surface);
    border: 1px dashed var(--line-strong);
    border-radius: var(--radius-lg);
}

.devices__quota {
    display: flex;
    gap: var(--space-3);
    margin: var(--space-4) 0 0;
    padding: var(--space-4);
    font-size: .8125rem;
    line-height: 1.55;
    color: var(--text-secondary);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    max-width: none;
}

.devices__quota svg { width: 17px; height: 17px; flex: none; color: var(--text-muted); }

.device-list { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-3); }

.device {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-4);
    flex-wrap: wrap;
    padding: var(--space-4);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    transition: border-color .2s var(--ease);
}

.device:hover { border-color: var(--line-strong); }

.device__main { display: flex; align-items: center; gap: var(--space-4); min-width: 0; flex: 1 1 15rem; }

.device__icon {
    display: grid;
    place-items: center;
    flex: none;
    width: 36px;
    height: 36px;
    border-radius: var(--radius-md);
    color: var(--text-secondary);
    background: var(--bg-inset);
    border: 1px solid var(--line);
}

.device__icon svg { width: 18px; height: 18px; }

/* A machine that has phoned home recently is the normal case, and saying so
   quietly is what makes the one that has NOT stand out. */
.device__icon.is-live { color: var(--success-fg); background: var(--success-bg); border-color: var(--success-line); }

.device__name { margin: 0; font-weight: 640; color: var(--text); }
.device__meta { margin: 2px 0 0; font-size: .75rem; color: var(--text-muted); }

.device__actions { display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap; }
.device__rename { display: flex; gap: var(--space-2); align-items: center; }

.field__input--compact {
    padding: .4rem .6rem;
    font-size: .8125rem;
    width: 11rem;
}

/* The release button is disabled once the 30-day quota is spent. Without this
   it stayed indistinguishable from a live control and people kept pressing it. */
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn:disabled:hover { background: var(--surface); border-color: var(--line); transform: none; }


/* ==========================================================================
   Public website — Phase 11
   ========================================================================== */

.page-lede {
    max-width: var(--measure);
    margin: -0.75rem 0 var(--space-8);
    font-size: 1.05rem;
    color: var(--ink-500);
}

.btn--large { padding: .85rem 1.6rem; font-size: 1.0625rem; }

/* ------------------------------------------------------------- Features */

.feature-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: var(--space-4);
}

.feature {
    position: relative;
    padding: var(--space-6);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    transition: border-color .2s var(--ease), box-shadow .2s var(--ease),
                transform .2s var(--ease);
}

.feature:hover {
    border-color: var(--accent-line);
    box-shadow: var(--shadow-md);
    transform: translateY(-2px);
}

.feature__icon {
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    margin-bottom: var(--space-4);
    border-radius: var(--radius-md);
    color: var(--accent-text);
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
}

.feature__icon svg { width: 20px; height: 20px; display: block; }

.feature__title { margin: 0 0 var(--space-2); font-size: 1.05rem; color: var(--text); }
.feature__body { margin: 0; font-size: .9375rem; line-height: 1.65; color: var(--text-secondary); }

/* ----------------------------------------------------------- Comparison */

.comparison {
    overflow-x: auto;
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    background: var(--surface);
    box-shadow: var(--shadow-sm);
}

.comparison__table {
    width: 100%;
    min-width: 640px;
    border-collapse: collapse;
    background: transparent;
}

.comparison__table th,
.comparison__table td {
    padding: var(--space-4);
    text-align: left;
    font-size: .9375rem;
    border-bottom: 1px solid var(--line);
}

.comparison__table thead th {
    font-size: .75rem;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--text-muted);
    background: var(--bg-inset);
}

/* THE TINT MOVED FROM "LAST COLUMN" TO "THE FEATURED ONE".

   This table used to have two columns, Free and Licensed, and tinting the last
   of them highlighted the one the page argues for. It now has one column per
   plan, so last-child had quietly come to mean Max — drawing the eye to the most
   expensive tier rather than to the recommended one, which is both wrong and the
   kind of wrong that looks deliberate.

   The view marks the featured plan's cells instead, so the highlight follows
   whichever plan is flagged in the admin panel. */
.comparison__table thead th.is-featured {
    color: var(--accent-text);
    background: var(--accent-soft);
}

.comparison__table tbody td.is-featured { background: var(--accent-soft); }

.comparison__table tbody th { font-weight: 600; color: var(--ink-700); }
.comparison__table tr:last-child th,
.comparison__table tr:last-child td { border-bottom: 0; }

.comparison__no { color: var(--text-muted); }

.comparison__yes {
    color: var(--success-fg);
    font-weight: 600;
}

.comparison__yes::before {
    content: "✓";
    margin-right: .4rem;
    font-weight: 700;
}

/* ------------------------------------------------------------- CTA band */

.cta-band {
    position: relative;
    overflow: hidden;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-6);
    flex-wrap: wrap;
    margin-top: var(--space-8);
    padding: var(--space-8);
    background: var(--grad-brand);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-lg);
    color: var(--text-on-accent);
}

.cta-band::after {
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(30rem 18rem at 88% 120%, rgba(34, 211, 238, .35), transparent 65%);
    pointer-events: none;
}

.cta-band > * { position: relative; z-index: 1; }

.cta-band--large { padding: var(--space-12) var(--space-8); }

.cta-band__title {
    margin: 0 0 var(--space-2);
    font-size: clamp(1.35rem, 2.6vw, 1.9rem);
    font-weight: 650;
    letter-spacing: -.02em;
    color: var(--text-on-accent);
}

.cta-band__note { margin: 0; font-size: 1rem; color: var(--on-accent-muted); }
.cta-band__actions { display: flex; gap: var(--space-3); flex-wrap: wrap; }

/*
  Inside the band the neutral button variants would disappear, so they are
  remapped rather than every call site being edited.

  The remap is by token now, not by literal white. On the dark theme the band is
  electric cyan and the button that has to stand on it is OBSIDIAN — a white
  button on cyan is two bright things arguing. On the light theme the band is
  deep teal and the polarity flips back to white. One pair of tokens, both
  answers, and no possibility of a screen where only one of them was updated.
*/
.cta-band .btn--primary,
.cta-band .btn--ghost {
    background: var(--on-accent-btn);
    border-color: transparent;
    color: var(--on-accent-btn-fg);
    box-shadow: var(--shadow-md);
}

.cta-band .btn--ghost {
    background: var(--on-accent-fill);
    border-color: var(--on-accent-line);
    color: var(--text-on-accent);
    box-shadow: none;
}

.cta-band .btn--ghost:hover {
    background: var(--on-accent-line);
    border-color: var(--text-on-accent);
    color: var(--text-on-accent);
}

.cta-band .btn--primary:hover {
    color: var(--on-accent-btn-fg);
    filter: brightness(1.15);
}

/* ------------------------------------------------------------- Download */

.download-meta {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
    margin: 0;
    padding: .4rem .9rem;
    font-size: .8125rem;
    color: var(--text-secondary);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-pill);
}

.download-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: var(--space-4);
}

.download-card {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: var(--space-8) var(--space-6);
    text-align: center;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    transition: border-color .2s var(--ease), box-shadow .2s var(--ease),
                transform .2s var(--ease);
}

.download-card:hover {
    border-color: var(--accent-line);
    box-shadow: var(--shadow-md);
    transform: translateY(-2px);
}

.download-card--soon { opacity: .72; box-shadow: none; }
.download-card--soon:hover { transform: none; border-color: var(--line); box-shadow: none; }

.download-card__icon {
    display: grid;
    place-items: center;
    width: 52px;
    height: 52px;
    margin: 0 auto var(--space-4);
    border-radius: var(--radius-md);
    color: var(--accent-text);
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
}

.download-card__icon svg { width: 26px; height: 26px; }
.download-card__title { margin: 0 0 var(--space-1); font-size: 1.1rem; color: var(--text); }
.download-card__note { margin: 0 0 var(--space-6); font-size: .8125rem; color: var(--text-muted); }
.download-card .btn { margin-top: auto; }

.download-keys {
    padding: var(--space-6);
    background: var(--success-bg);
    border: 1px solid var(--success-line);
    border-radius: var(--radius-lg);
}

.download-keys__title { margin: 0 0 var(--space-2); font-size: 1.05rem; color: var(--text); }
.download-keys__note { margin: 0 0 var(--space-4); font-size: .875rem; color: var(--ink-700); }

.install-steps {
    padding: var(--space-8);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
}

.install-steps__title { margin: 0 0 var(--space-4); font-size: 1.05rem; color: var(--text); }
.install-steps__list { margin: 0 0 var(--space-4); padding-left: 1.3rem; }
.install-steps__list li { margin-bottom: var(--space-3); font-size: .9375rem; line-height: 1.6; }
.install-steps__note { margin: 0; font-size: .875rem; color: var(--text-secondary); }

/* -------------------------------------------------------------- Contact */

.contact {
    display: grid;
    grid-template-columns: minmax(0, 1.5fr) minmax(240px, 1fr);
    gap: var(--space-8);
    align-items: start;
}

@media (max-width: 820px) {
    .contact { grid-template-columns: minmax(0, 1fr); }
}

/* Hidden from people without display:none — some bots skip those, and this one
   is meant to be filled in by them. */
.contact__trap {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.contact__form {
    padding: var(--space-8);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

.contact__form-title { margin: 0 0 var(--space-2); font-size: 1.25rem; }
.contact__form-lede { margin: 0 0 var(--space-6); font-size: .9375rem; color: var(--text-secondary); }

.contact__aside {
    padding: var(--space-6);
    background: var(--bg-inset);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
}

.contact__aside-title {
    margin: 0 0 var(--space-4);
    font-size: .75rem;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--text-muted);
}

.contact__faq { margin: 0; }
.contact__faq dt { font-weight: 650; font-size: .875rem; color: var(--text); margin-bottom: 2px; }
.contact__faq dd { margin: 0 0 var(--space-4); font-size: .875rem; line-height: 1.55; color: var(--text-secondary); }

.contact__direct {
    margin: 0;
    padding-top: var(--space-4);
    border-top: 1px solid var(--line);
    font-size: .875rem;
}

/* Three facts about getting a reply, shown before the form so nobody has to
   guess how long to wait. */
.contact-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: var(--space-4);
    margin-bottom: var(--space-12);
}

.contact-fact {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-6);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
}

.contact-fact__icon {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    flex: none;
    border-radius: var(--radius-sm);
    color: var(--accent-text);
    background: var(--accent-soft);
}

.contact-fact__icon svg { width: 17px; height: 17px; }
.contact-fact__title { display: block; font-size: .875rem; font-weight: 650; color: var(--text); }
.contact-fact__body { display: block; font-size: .8125rem; color: var(--text-secondary); }

/* ----------------------------------------------------------- Legal pages */

.legal-head { margin-bottom: var(--space-8); }
.legal-head__meta { margin: -0.75rem 0 0; font-size: .8125rem; color: var(--text-muted); }

.legal-foot {
    margin-top: var(--space-12);
    padding-top: var(--space-6);
    border-top: 1px solid var(--line);
    font-size: .875rem;
    color: var(--text-secondary);
}

.legal-foot p { margin: 0; max-width: none; }

/* Sibling policies, so a visitor who landed on Terms can reach Privacy without
   going back to the footer. */
.legal-nav {
    max-width: 52rem;
    margin: var(--space-8) auto 0;
    text-align: center;
}

.legal-nav__title {
    display: block;
    margin-bottom: var(--space-3);
    font-size: .6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .1em;
    color: var(--text-muted);
}

.legal-nav__list {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.legal-nav__list a {
    display: inline-block;
    padding: .45rem .9rem;
    font-size: .875rem;
    color: var(--text-secondary);
    text-decoration: none;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-pill);
    transition: border-color .15s var(--ease), color .15s var(--ease);
}

.legal-nav__list a:hover { border-color: var(--accent-line); color: var(--accent-text); }

/* Long-form prose on a panel, so an essay-length page still has an edge and a
   measure rather than floating in the middle of a wide viewport. */
.prose-card {
    max-width: 52rem;
    margin-inline: auto;
    padding: var(--space-12);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

.prose-card .prose { max-width: none; }

@media (max-width: 640px) {
    .prose-card { padding: var(--space-6); }
}

/* Long-form prose, used by CMS pages and the about page. */
.prose { max-width: var(--measure); font-size: 1rem; line-height: 1.75; color: var(--ink-700); }

.prose__lede { font-size: 1.15rem; line-height: 1.6; color: var(--ink-900); }

.prose h2 {
    margin: var(--space-8) 0 var(--space-3);
    font-size: 1.3rem;
    line-height: 1.3;
    color: var(--ink-900);
}

.prose h3 { margin: var(--space-6) 0 var(--space-2); font-size: 1.1rem; color: var(--ink-900); }
.prose h2:first-child, .prose h3:first-child { margin-top: 0; }
.prose p { margin: 0 0 var(--space-4); }
.prose ul, .prose ol { margin: 0 0 var(--space-4); padding-left: 1.4rem; }
.prose li { margin-bottom: var(--space-2); }
.prose strong { color: var(--ink-900); }

.prose a { color: var(--brand-600); }

.prose blockquote {
    margin: 0 0 var(--space-4);
    padding: var(--space-3) var(--space-4);
    border-left: 3px solid var(--warn-600);
    background: var(--warn-100);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.prose blockquote p { margin: 0; }

.prose code {
    padding: .1rem .3rem;
    font-family: var(--font-mono);
    font-size: .875em;
    background: var(--ink-50);
    border-radius: 3px;
}

.prose hr { margin: var(--space-8) 0; border: 0; border-top: 1px solid var(--ink-100); }

/* --------------------------------------------------------------- Footer */

.site-footer__grid {
    display: grid;
    grid-template-columns: minmax(0, 2fr) repeat(3, minmax(0, 1fr));
    gap: var(--space-8);
    padding: var(--space-12) 0 var(--space-8);
}

@media (max-width: 760px) {
    .site-footer__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-6); }
    .site-footer__brand { grid-column: 1 / -1; }
}

.site-footer__brand .brand { margin-bottom: var(--space-4); }
.site-footer__name { margin: 0 0 var(--space-2); font-weight: 650; color: var(--text); }
.site-footer__blurb { margin: 0 0 var(--space-4); font-size: .875rem; line-height: 1.6; color: var(--text-secondary); max-width: 34ch; }

.site-footer__badges {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.site-footer__badges li {
    padding: .2rem .6rem;
    font-size: .6875rem;
    font-weight: 600;
    letter-spacing: .02em;
    color: var(--text-secondary);
    background: var(--bg-inset);
    border: 1px solid var(--line);
    border-radius: var(--radius-pill);
}

.site-footer__heading {
    margin: 0 0 var(--space-3);
    font-size: .6875rem;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--ink-300);
}

.site-footer__column { display: flex; flex-direction: column; gap: var(--space-2); }
.site-footer__column a { font-size: .875rem; color: var(--ink-500); text-decoration: none; }
.site-footer__column a:hover { color: var(--brand-600); }

.site-footer__base {
    display: flex;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
    padding: var(--space-6) 0;
    border-top: 1px solid var(--line);
}

/* ==========================================================================
   Landing page components

   Everything below belongs to the marketing pages. It is deliberately
   image-free: the product shot, the meters and the platform marks are all
   drawn in CSS, so the page has no art dependency, no layout shift, and no
   second request before it looks finished.
   ========================================================================== */

/* ----------------------------------------------------------- Page heroes

   Every page other than the landing page opens the same way: mesh background,
   kicker, title, one paragraph. Having one block for it is what stops the
   secondary pages from slowly drifting into five different headers.
   -------------------------------------------------------------------------- */

.page-hero {
    position: relative;
    overflow: hidden;
    padding: var(--space-16) 0 var(--space-12);
    background: var(--grain), var(--grad-mesh), var(--bg);
    border-bottom: 1px solid var(--line);
    text-align: center;
}

.page-hero::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image:
        linear-gradient(to right, var(--line) 1px, transparent 1px),
        linear-gradient(to bottom, var(--line) 1px, transparent 1px);
    background-size: 64px 64px;
    opacity: .45;
    mask-image: radial-gradient(70% 70% at 50% 20%, #000 20%, transparent 75%);
    -webkit-mask-image: radial-gradient(70% 70% at 50% 20%, #000 20%, transparent 75%);
    pointer-events: none;
}

.page-hero__inner {
    position: relative;
    max-width: 46rem;
    margin-inline: auto;
}

.page-hero__title {
    font-size: clamp(2rem, 4.4vw, 3rem);
    letter-spacing: -.035em;
    margin-bottom: var(--space-4);
}

.page-hero__lede {
    margin: 0 auto;
    font-size: clamp(1rem, 1.4vw, 1.125rem);
    color: var(--text-secondary);
}

.page-hero__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-3);
    margin-top: var(--space-8);
}

.page-hero__meta {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-2) var(--space-4);
    margin: var(--space-6) 0 0;
    font-size: .8125rem;
    color: var(--text-muted);
    max-width: none;
}

.page-hero__meta strong { color: var(--text); font-weight: 600; }

/* --------------------------------------------------------------------------
   Hero byline with a portrait — the About page's "who is behind this" line.

   A face is the cheapest trust signal a one-person product has, and the About
   page is where the reader is deciding whether to hand money to a vendor they
   have not heard of. So it sits inline with the name rather than in a card of
   its own: the photo and the name are one statement, and splitting them into
   two blocks would only push the page's actual argument further down.

   The source image is a circular crop already, on a pale ground. `border-radius`
   is still applied here, because the file's square corners are white and would
   show as a white box in dark mode. The ring is a translucent border rather than
   a solid colour so it reads correctly against both themes without a second
   rule.
   -------------------------------------------------------------------------- */
.page-hero__byline {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    margin: var(--space-8) 0 0;
    font-size: .875rem;
    color: var(--text-muted);
    text-align: left;
}

.page-hero__portrait {
    flex: none;
    width: 3.5rem;
    height: 3.5rem;
    border-radius: 50%;
    object-fit: cover;
    /* The photograph's own background is near-white; on a light page it would
       otherwise dissolve into the hero with no edge at all. */
    border: 1px solid rgb(0 0 0 / .08);
    box-shadow: var(--shadow-sm, 0 1px 2px rgb(0 0 0 / .06));
}

.page-hero__byline strong {
    display: block;
    color: var(--text);
    font-weight: 600;
    font-size: .9375rem;
    letter-spacing: -.01em;
}

.page-hero__byline-role {
    display: block;
    margin-top: .125rem;
    font-size: .8125rem;
    color: var(--text-muted);
}

@media (max-width: 30rem) {
    /* Stacked, because at this width the two-line name block and a 56px circle
       leave the role text wrapping mid-phrase. */
    .page-hero__byline {
        flex-direction: column;
        gap: var(--space-2);
        text-align: center;
    }
}

/* The hero already carries generous bottom space; a full section rhythm on top
   of it leaves a hole between the title and the first thing you can act on. */
.page-hero + .section { padding-top: var(--space-16); }

/* ==========================================================================
   Account area — dashboard, licences, usage, orders, password

   Every signed-in page opens the same way: a tinted band carrying who you are,
   what this screen is, and the row of tabs. Below it the page is plain.

   It is louder than it was. The old band was a title on flat grey, which made
   the signed-in half of the site look like a different, cheaper product than
   the one people had just paid for — so it now takes the marketing pages'
   mesh and grid, at a fraction of the intensity, and the tabs became pills
   because a row of underlines is invisible until you already know it is there.
   ========================================================================== */

.account-shell {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    padding: var(--space-12) 0 0;
    background: var(--grain), var(--grad-mesh), var(--bg-subtle);
    border-bottom: 1px solid var(--line);
}

.account-shell::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background-image:
        linear-gradient(to right, var(--line) 1px, transparent 1px),
        linear-gradient(to bottom, var(--line) 1px, transparent 1px);
    background-size: 56px 56px;
    mask-image: radial-gradient(60% 80% at 50% 0%, #000 5%, transparent 80%);
    -webkit-mask-image: radial-gradient(60% 80% at 50% 0%, #000 5%, transparent 80%);
    pointer-events: none;
}

.account-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4) var(--space-6);
    margin-bottom: var(--space-8);
}

.account-head__ident {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    min-width: 0;
}

/* The initial. It is the one element on the band that is different for each
   person looking at it, which is most of the reason the band feels like an
   account rather than a page template. */
.account-head__avatar {
    display: grid;
    place-items: center;
    flex: none;
    width: 56px;
    height: 56px;
    border-radius: var(--radius-lg);
    background: var(--grad-brand);
    color: var(--text-on-accent);
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -.02em;
    box-shadow: var(--shadow-accent);
}

.account-head__eyebrow {
    margin: 0 0 var(--space-1);
    font-size: .6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: var(--accent-text);
}

.account-head__title {
    margin: 0 0 var(--space-2);
    font-size: clamp(1.5rem, 3.2vw, 2.125rem);
    letter-spacing: -.035em;
}

.account-head__lede {
    margin: 0;
    font-size: .9375rem;
    color: var(--text-secondary);
}

.account-head__lede strong { color: var(--text); font-weight: 600; }

.account-head__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/*
  Tabs as pills, sitting on the band's bottom edge.

  The current one is a filled chip rather than an underline: this row scrolls
  sideways on a phone, and a two-pixel rule under a word that is half off the
  screen tells nobody where they are.
*/
.account-nav {
    display: flex;
    gap: var(--space-2);
    overflow-x: auto;
    padding-bottom: var(--space-4);
    scrollbar-width: none;
}

.account-nav::-webkit-scrollbar { display: none; }

.account-nav a {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    flex: none;
    padding: .5rem .95rem;
    border: 1px solid transparent;
    border-radius: var(--radius-pill);
    font-size: .875rem;
    font-weight: 570;
    color: var(--text-secondary);
    text-decoration: none;
    white-space: nowrap;
    transition: color .15s var(--ease), background-color .15s var(--ease),
                border-color .15s var(--ease);
}

.account-nav a svg { width: 16px; height: 16px; flex: none; opacity: .8; }

.account-nav a:hover {
    color: var(--text);
    background: var(--bg-inset);
}

.account-nav a.is-current {
    color: var(--accent-text);
    background: var(--accent-soft);
    border-color: var(--accent-line);
}

.account-nav a.is-current svg { opacity: 1; }

.account-nav__count {
    display: inline-block;
    min-width: 1.25rem;
    padding: 0 .35rem;
    font-size: .6875rem;
    font-weight: 700;
    line-height: 1.25rem;
    text-align: center;
    color: var(--text-secondary);
    background: var(--bg-inset);
    border-radius: var(--radius-pill);
}

.account-nav a.is-current .account-nav__count {
    color: var(--text-on-accent);
    background: var(--accent);
}

/* The band carries its own bottom space; a full section rhythm on top of it
   leaves a hole between the tabs and the first tile. */
.account-shell + .section { padding-top: var(--space-8); }

/* ------------------------------------------------------ Headline numbers -- */

.tile-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: var(--space-4);
    margin-bottom: var(--space-8);
}

.tile {
    position: relative;
    overflow: hidden;
    display: block;
    padding: var(--space-6);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    text-decoration: none;
    transition: border-color .2s var(--ease), box-shadow .2s var(--ease),
                transform .2s var(--ease);
}

/* Most tiles are links to the screen that manages the thing they count. Only
   those get the lift — a tile that does not go anywhere should not offer. */
a.tile:hover {
    border-color: var(--accent-line);
    box-shadow: var(--shadow-md);
    transform: translateY(-2px);
}

.tile__icon {
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    margin-bottom: var(--space-4);
    border-radius: var(--radius-md);
    color: var(--accent-text);
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
}

.tile__icon svg { width: 19px; height: 19px; }

.tile--violet .tile__icon {
    color: var(--violet-text);
    background: var(--violet-soft);
    border-color: var(--violet-line);
}

.tile__value {
    display: block;
    font-size: 2rem;
    font-weight: 700;
    line-height: 1.05;
    letter-spacing: -.035em;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

.tile__label {
    display: block;
    margin-top: var(--space-1);
    font-size: .875rem;
    color: var(--text-secondary);
}

.tile__note {
    display: block;
    margin-top: var(--space-3);
    font-size: .75rem;
    font-weight: 600;
    color: var(--accent-text);
}

/* ----------------------------------------------------- Dashboard layout --- */

/*
  Two columns: the things you came to do on the left, the things you came to
  check on the right. Collapses to one at 940px, main column first, because
  "where is my key" beats "when did I join" on every screen size.
*/
.acct-layout {
    display: grid;
    grid-template-columns: minmax(0, 1.65fr) minmax(0, 1fr);
    gap: var(--space-6);
    align-items: start;
}

@media (max-width: 940px) {
    .acct-layout { grid-template-columns: minmax(0, 1fr); }
}

.acct-main,
.acct-side { display: grid; gap: var(--space-6); align-content: start; }

.acct-side .panel-card { margin-bottom: 0; }

/*
  The licence spotlight.

  The overview page used to be three counters and four identical grey cards,
  and the one thing every visit is actually about — the key — was two clicks
  away behind the word "Manage". So the newest usable licence is promoted onto
  this screen in full: key, expiry, devices, and what is left of the month.
*/
.spotlight {
    position: relative;
    overflow: hidden;
    padding: var(--space-6);
    background: var(--grad-spot), var(--surface);
    border: 1px solid var(--accent-line);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-md);
}

.spotlight__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
    margin-bottom: var(--space-4);
}

.spotlight__eyebrow {
    margin: 0 0 var(--space-1);
    font-size: .6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .11em;
    color: var(--text-muted);
}

.spotlight__plan {
    margin: 0 0 var(--space-2);
    font-size: 1.375rem;
    letter-spacing: -.025em;
}

.spotlight__badges { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: 0; }

.spotlight__stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: var(--space-4);
    margin: var(--space-6) 0 0;
    padding-top: var(--space-6);
    border-top: 1px solid var(--line);
}

.spotlight__stats dt {
    font-size: .6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .09em;
    color: var(--text-muted);
}

.spotlight__stats dd {
    margin: var(--space-1) 0 0;
    font-size: .9375rem;
    font-weight: 640;
    color: var(--text);
}

.spotlight__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-top: var(--space-6);
}

.spotlight__more {
    margin: var(--space-4) 0 0;
    font-size: .8125rem;
    color: var(--text-muted);
}

/* ------------------------------------------------------------ Action cards */

.action-card {
    display: flex;
    flex-direction: column;
    padding: var(--space-6);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    text-decoration: none;
    transition: border-color .2s var(--ease), box-shadow .2s var(--ease),
                transform .2s var(--ease);
}

.action-card:hover {
    border-color: var(--accent-line);
    box-shadow: var(--shadow-md);
    transform: translateY(-2px);
}

.action-card__icon {
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    margin-bottom: var(--space-4);
    border-radius: var(--radius-md);
    color: var(--accent-text);
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
}

.action-card__icon svg { width: 18px; height: 18px; }

.action-card__title {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0 0 var(--space-2);
    font-size: 1.0625rem;
    color: var(--text);
}

/* The arrow leans in on hover. Small, but it is the only affordance saying the
   whole card is the link rather than the words inside it. */
.action-card__title svg {
    width: 16px;
    height: 16px;
    color: var(--accent);
    transition: transform .2s var(--ease);
}

.action-card:hover .action-card__title svg { transform: translateX(3px); }

.action-card__body {
    margin: 0;
    font-size: .875rem;
    line-height: 1.55;
    color: var(--text-secondary);
}

/* --------------------------------------------- Panels shared by the screens */

.panel-card {
    margin-bottom: var(--space-6);
    padding: var(--space-6);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

.panel-card__title {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0 0 var(--space-4);
    font-size: .9375rem;
    letter-spacing: -.01em;
    color: var(--text);
}

.panel-card__title svg { width: 17px; height: 17px; color: var(--text-muted); }

.detail-list {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: var(--space-3) var(--space-4);
    margin: 0;
    font-size: .875rem;
}

.detail-list dt { color: var(--text-muted); }
.detail-list dd { margin: 0; color: var(--text); text-align: right; font-weight: 550; }

.panel-card .detail-list + .btn { margin-top: var(--space-6); }

.empty-state {
    padding: var(--space-16) var(--space-6);
    text-align: center;
    background: var(--grad-spot), var(--surface);
    border: 1px dashed var(--line-strong);
    border-radius: var(--radius-xl);
}

.empty-state__icon {
    display: grid;
    place-items: center;
    width: 52px;
    height: 52px;
    margin: 0 auto var(--space-4);
    border-radius: var(--radius-lg);
    color: var(--accent-text);
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
}

.empty-state__icon svg { width: 24px; height: 24px; }

.dashboard__admin-link {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
    margin-top: var(--space-8);
    padding: var(--space-4) var(--space-6);
    background: var(--violet-soft);
    border: 1px solid var(--violet-line);
    border-radius: var(--radius-lg);
    font-size: .875rem;
    color: var(--text-secondary);
    max-width: none;
}


/* ==========================================================================
   Checkout shell

   A three-step purchase deserves to say which step you are on. The band below
   carries that, and the summary column sticks so the total stays in view while
   the payment methods are read.
   ========================================================================== */

.checkout-shell {
    padding: var(--space-12) 0;
    background: var(--grad-spot), var(--bg-subtle);
    border-bottom: 1px solid var(--line);
    text-align: center;
}

.checkout-shell__title {
    margin: 0 0 var(--space-6);
    font-size: clamp(1.5rem, 3.2vw, 2.125rem);
    letter-spacing: -.03em;
}

.progress-steps {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: var(--space-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.progress-step {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    padding: .4rem .9rem .4rem .45rem;
    font-size: .875rem;
    font-weight: 550;
    color: var(--text-muted);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-pill);
}

.progress-step__num {
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    flex: none;
    border-radius: 50%;
    font-size: .75rem;
    font-weight: 700;
    color: var(--text-muted);
    background: var(--bg-inset);
}

.progress-step.is-current {
    color: var(--accent-text);
    border-color: var(--accent-line);
    background: var(--accent-soft);
}

.progress-step.is-current .progress-step__num {
    color: var(--text-on-accent);
    background: var(--accent);
}

.progress-step.is-done { color: var(--success-fg); border-color: var(--success-line); background: var(--success-bg); }
.progress-step.is-done .progress-step__num { color: var(--bg); background: var(--success-fg); }

.progress-steps__sep { color: var(--text-muted); }

@media (max-width: 620px) {
    .progress-steps__sep { display: none; }
    .progress-step { font-size: .8125rem; }
}

/* ==========================================================================
   Hero product shot — the desktop app, rebuilt in markup

   Not a screenshot. A screenshot of a dark application on a dark page is a
   rectangle of noise at any width the hero can spare, it cannot animate, and it
   goes stale the first time the rail is reordered. This is the same layout in
   the same palette, at a size that is legible, with the one interaction the
   product is actually about — before and after — live in it.

   The parts mirror the app's own names so the two stay recognisable as one
   thing: a rail on the left holding the tools, a stage on the right holding the
   material, and the verb along the bottom.
   ========================================================================== */

.hero__visual {
    position: relative;
    perspective: 1500px;
}

.app-shot {
    position: relative;
    border-radius: var(--radius-lg);
    border: 1px solid var(--line-strong);
    background: var(--p-panel);
    box-shadow: var(--shadow-lg), 0 0 0 1px rgba(34, 211, 238, .06);
    overflow: hidden;
    /* A shallow turn, hinged on the left edge so the window appears to open
       towards the copy rather than lean away from it. Removed outright below
       the breakpoint, where the visual is full width and any rotation just
       costs legibility. */
    transform: rotateY(-7deg) rotateX(3deg) translateZ(0);
    transform-origin: left center;
}

@media (max-width: 980px) {
    .app-shot { transform: none; }
}

.app-shot__bar {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: .6rem var(--space-4);
    background: var(--p-void);
    border-bottom: 1px solid var(--line);
}

.app-shot__dots { display: flex; gap: 6px; }

.app-shot__dots i {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: rgba(255, 255, 255, .13);
}

.app-shot__title {
    font-size: .75rem;
    font-weight: 620;
    color: #8a94a5;
    letter-spacing: .01em;
}

.app-shot__body {
    display: grid;
    /* Wide enough for "Normalise loudness" on one line. At 158px it wrapped,
       and a rail of two-line tool names is the one thing the real app's rail
       never does. */
    grid-template-columns: 178px minmax(0, 1fr);
    min-height: 360px;
}

/* ------------------------------------------------------------------- Rail */

.app-rail {
    padding: var(--space-4) var(--space-3);
    border-right: 1px solid var(--line);
    background: var(--p-void);
}

.app-rail__title {
    margin: 0 0 var(--space-3);
    padding-left: .35rem;
    font-size: .625rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .1em;
    color: #5c6675;
}

.app-rail__group + .app-rail__group { margin-top: var(--space-2); }

/*
  The Audio | Video tab pair, mirroring the application's own rail.

  The app replaced two drawers with one segmented control, for the reason a
  drawer could not carry: a run is either audio or video, never both, and a tab
  says "pick one" where an accordion says "open as many as you like". The
  marketing shot follows it rather than keeping the old shape alive.
*/
.app-rail__tabs {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2px;
    padding: 2px;
    margin-bottom: var(--space-2);
    border-radius: var(--radius-sm);
    background: rgba(255, 255, 255, .035);
    border: 1px solid var(--line);
}

.app-rail__tab {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .35rem;
    padding: .35rem .3rem;
    border-radius: calc(var(--radius-sm) - 2px);
    font-size: .75rem;
    font-weight: 600;
    color: #68738a;
}

.app-rail__tab svg { width: 14px; height: 14px; flex: none; }

.app-rail__tab.is-active {
    background: var(--p-n-900, #11151a);
    color: var(--p-cyan-400);
}

.app-rail__tab:not(.is-active) svg { color: var(--p-violet-400); }

.app-rail__tab i {
    font-style: normal;
    font-size: .625rem;
    font-weight: 700;
    padding: 0 .3rem;
    border-radius: 99px;
    background: var(--p-cyan-400);
    color: #04161c;
}

.app-rail__note {
    margin: 0 0 var(--space-2);
    padding-left: .35rem;
    font-size: .625rem;
    color: #5c6675;
}

.app-rail__head {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .45rem .5rem;
    border-radius: var(--radius-sm);
    font-size: .8125rem;
    font-weight: 600;
    color: #c3cbd7;
}

.app-rail__head svg { width: 16px; height: 16px; flex: none; color: var(--p-cyan-400); }
.app-rail__head--video svg { color: var(--p-violet-400); }

.app-rail__head i {
    margin-left: auto;
    font-style: normal;
    font-size: .625rem;
    font-weight: 600;
    color: var(--p-cyan-400);
}

.app-rail__group.is-open .app-rail__head {
    background: rgba(34, 211, 238, .09);
    color: #eef2f7;
}

/*
  The ticked tools.

  Each row lands a beat after the one above it — the same sweep the app runs
  when a chain starts, and the reason the panel reads as something in progress
  rather than a still. It plays once: a rail that keeps re-ticking itself every
  four seconds is a rail nobody looks at twice.
*/
.app-tick {
    display: flex;
    align-items: center;
    gap: .45rem;
    padding: .34rem .4rem .34rem 1.15rem;
    font-size: .75rem;
    white-space: nowrap;
    color: #8a94a5;
}

/*
  UNTICKED IS AN EMPTY OUTLINE, TICKED IS FILLED — the same pair the app draws.

  This rule used to fill and light every box, because the rail mock only ever
  contained ticked rows. The moment it gained unticked ones, all six read as
  chosen while the tab badge beside them said three. A picture that contradicts
  its own label is worse than no picture.
*/
.app-tick svg {
    width: 11px;
    height: 11px;
    flex: none;
    padding: 2px;
    border-radius: 4px;
    color: transparent;
    background: transparent;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .16);
}

.app-tick.is-on svg {
    color: var(--p-cyan-ink);
    background: var(--p-cyan-400);
    box-shadow: 0 0 12px rgba(34, 211, 238, .45);
}

.app-tick.is-on { color: #c3cbd7; }

.js .app-tick.is-on {
    opacity: 0;
    animation: tick-in .45s var(--ease-out) forwards;
}

/* Counted with nth-CHILD, not nth-of-type. The group's heading is a <span> too,
   so it is child 1 and the five ticks are children 2 to 6 — nth-of-type would
   silently leave the last tick without a delay, and it would arrive first. */
.js .app-tick.is-on:nth-child(2) { animation-delay: .55s; }
.js .app-tick.is-on:nth-child(3) { animation-delay: .70s; }
.js .app-tick.is-on:nth-child(4) { animation-delay: .85s; }
.js .app-tick.is-on:nth-child(5) { animation-delay: 1.00s; }
.js .app-tick.is-on:nth-child(6) { animation-delay: 1.15s; }

@keyframes tick-in {
    from { opacity: 0; transform: translateX(-6px); }
    to   { opacity: 1; transform: none; }
}

/* ------------------------------------------------------------------ Stage */

.app-stage {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    padding: var(--space-4);
}

.app-stage__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
}

.app-stage__file {
    font-family: var(--font-mono);
    font-size: .6875rem;
    color: #8a94a5;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* A two-position segmented control, and the only thing on the page that asks
   to be pressed before the buttons in the hero copy do. */
.app-compare {
    display: inline-flex;
    flex: none;
    padding: 2px;
    border-radius: var(--radius-pill);
    background: rgba(255, 255, 255, .05);
    border: 1px solid var(--line);
}

.app-compare button {
    padding: .22rem .7rem;
    border: 0;
    border-radius: var(--radius-pill);
    background: transparent;
    font: inherit;
    font-size: .6875rem;
    font-weight: 620;
    color: #8a94a5;
    cursor: pointer;
    transition: color .18s var(--ease), background-color .18s var(--ease);
}

.app-compare button:hover { color: #eef2f7; }

.app-compare button.is-active {
    color: var(--p-cyan-ink);
    background: var(--p-cyan-400);
}

/* ----------------------------------------------------------- The waveform */

.app-stage__wave {
    position: relative;
    height: 108px;
    border-radius: var(--radius-md);
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .022), transparent 60%),
        var(--p-obsidian);
    border: 1px solid var(--line);
    overflow: hidden;
}

/*
  Two waveforms stacked in the same box, cross-faded rather than swapped.

  They are the same signal — the peaks line up bar for bar — because the claim
  being made is that the SPEECH survives and everything between it does not. If
  the two rows had different peaks the panel would be showing a different
  recording, which is the one thing it must not appear to do.
*/
.wave {
    position: absolute;
    inset: 12px;
    display: flex;
    align-items: center;
    /* 1px. At 2px the bars and the gaps were nearly the same width and the
       panel read as a bar chart; a waveform is dense, and the density is what
       makes the silences between the phrases legible as silences. */
    gap: 1px;
    transition: opacity .5s var(--ease-out);
}

.wave span {
    flex: 1 1 0;
    min-width: 0;
    height: var(--h);
    border-radius: 2px;
    transform-origin: center;
}

.wave--raw span {
    background: #3b4553;
}

.wave--clean span {
    background: linear-gradient(180deg, var(--p-cyan-300), var(--p-cyan-500));
    box-shadow: 0 0 10px rgba(34, 211, 238, .30);
}

.wave--clean { opacity: 0; }

[data-compare="after"] .wave--raw { opacity: 0; }
[data-compare="after"] .wave--clean { opacity: 1; }

/* The breathing is what stops the panel reading as a diagram. It is a scale on
   the Y axis only, staggered by the bar's own index, so 48 bars need one rule
   rather than 48 — and it is transform-only, so it never triggers layout. */
.js .wave span {
    animation: wave-breathe 2.4s var(--ease-app) infinite alternate;
    animation-delay: calc(var(--i) * -80ms);
}

@keyframes wave-breathe {
    from { transform: scaleY(.72); }
    to   { transform: scaleY(1); }
}

/* The playhead. Sweeps once every six seconds; long enough that it reads as
   playback rather than as a loading bar. */
.app-stage__playhead {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 1px;
    background: linear-gradient(180deg, transparent, var(--p-cyan-300), transparent);
    box-shadow: 0 0 14px 2px rgba(34, 211, 238, .45);
    opacity: 0;
}

.js .app-stage__playhead { animation: playhead 6s linear infinite; }

@keyframes playhead {
    0%        { left: 0;    opacity: 0; }
    6%        {             opacity: 1; }
    94%       {             opacity: 1; }
    100%      { left: 100%; opacity: 0; }
}

/* --------------------------------------------------------------- Readouts */

.app-stage__readout {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-3);
    margin: 0;
}

.app-stage__readout dt {
    font-size: .625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: #5c6675;
}

.app-stage__readout dd {
    margin: 2px 0 0;
    font-size: .8125rem;
    font-weight: 640;
    color: #c3cbd7;
    font-variant-numeric: tabular-nums;
}

/* Both figures ship in the markup and one is hidden, so the two states cannot
   fall out of step. With CSS unavailable the pair simply reads as "before,
   after", which is still the comparison. */
.app-stage__readout .is-after { display: none; }

[data-compare="after"] .app-stage__readout .is-before { display: none; }
[data-compare="after"] .app-stage__readout .is-after { display: inline; color: var(--p-cyan-300); }

/* --------------------------------------------------------------- Queue -- */

/* The rest of the batch, under the file being looked at. Deliberately quiet:
   it exists to say "there are others", and anything louder would compete with
   the waveform for the same glance. */
.app-queue {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 1px;
}

.app-queue li {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: .4rem .6rem;
    border-radius: var(--radius-sm);
    background: rgba(255, 255, 255, .022);
    font-family: var(--font-mono);
    font-size: .6875rem;
    color: #8a94a5;
}

.app-queue li span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.app-queue li em {
    flex: none;
    font-style: normal;
    font-family: var(--font-sans);
    font-size: .625rem;
    font-weight: 650;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: #5c6675;
}

/* Video takes the violet side, the same split the rail uses. */
.app-queue__video em { color: var(--p-violet-400); }

/* -------------------------------------------------------------- The verb */

.app-stage__run {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-top: auto;
    padding-top: var(--space-3);
    border-top: 1px solid var(--line);
}

.app-stage__runbar {
    flex: 1;
    height: 6px;
    border-radius: 4px;
    background: rgba(255, 255, 255, .06);
    overflow: hidden;
}

.app-stage__runbar span {
    display: block;
    width: 18%;
    height: 100%;
    border-radius: 4px;
    background: var(--grad-brand);
    box-shadow: 0 0 12px rgba(34, 211, 238, .5);
}

.js .app-stage__runbar span { animation: run-fill 6s var(--ease-app) infinite; }

@keyframes run-fill {
    0%   { width: 6%; }
    72%  { width: 84%; }
    92%, 100% { width: 100%; }
}

.app-stage__runlabel {
    flex: none;
    font-size: .6875rem;
    font-weight: 650;
    color: var(--p-cyan-300);
}

@media (max-width: 620px) {
    .app-shot__body { grid-template-columns: minmax(0, 1fr); }
    .app-rail { display: none; }
    .app-stage__readout { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* A floating card overlapping the window, carrying the one number the visual
   is meant to leave behind. */
.app-float {
    position: absolute;
    right: -14px;
    /* Clear of the run bar along the foot of the shot. At -18px the card sat on
       top of "Clean up everything", which is the one label in the mock that has
       to be readable. */
    bottom: -34px;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
}

.app-float__mark {
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border-radius: 8px;
    color: var(--accent);
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
}

.app-float__mark svg { width: 16px; height: 16px; }
.app-float__value { display: block; font-size: .8125rem; font-weight: 650; color: var(--text); }
.app-float__label { font-size: .6875rem; color: var(--text-muted); }

@media (max-width: 560px) { .app-float { display: none; } }

/* ------------------------------------------------------------- Stat strip */

.stat-band {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 1px;
    margin: 0;
    padding: 0;
    list-style: none;
    background: var(--line);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    overflow: hidden;
}

.stat {
    padding: var(--space-6);
    background: var(--surface);
    text-align: center;
}

.stat__value {
    display: block;
    font-size: clamp(1.5rem, 3vw, 2rem);
    font-weight: 700;
    letter-spacing: -.03em;
    line-height: 1.1;
    color: var(--text);
}

.stat__label {
    display: block;
    margin-top: var(--space-1);
    font-size: .8125rem;
    color: var(--text-secondary);
}

/* --------------------------------------------------------------- Platforms */

.pill-row {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.pill {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    padding: .45rem .9rem;
    font-size: .8125rem;
    font-weight: 550;
    color: var(--text-secondary);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-pill);
}

.pill svg { width: 15px; height: 15px; color: var(--text-muted); }

/* ------------------------------------------------------------------ Steps */

.steps {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: var(--space-6);
    counter-reset: step;
    margin: 0;
    padding: 0;
    list-style: none;
}

.step {
    position: relative;
    padding-top: var(--space-8);
}

/* The connector is drawn from the number outwards and clipped at the last
   item, so it never dangles off the end of the row. */
.step::before {
    content: "";
    position: absolute;
    top: 19px;
    left: 44px;
    right: calc(var(--space-6) * -1);
    height: 1px;
    background: linear-gradient(to right, var(--line-strong), transparent);
}

.step:last-child::before { display: none; }

@media (max-width: 760px) { .step::before { display: none; } }

.step__num {
    position: absolute;
    top: 0;
    left: 0;
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    font-size: .875rem;
    font-weight: 700;
    color: var(--accent-text);
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
}

.step__title { margin: 0 0 var(--space-2); font-size: 1.0625rem; }
.step__body { margin: 0; font-size: .9375rem; color: var(--text-secondary); }

/* -------------------------------------------------------------- Use cases */

.usecase-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: var(--space-4);
}

.usecase {
    padding: var(--space-6);
    border-radius: var(--radius-lg);
    border: 1px solid var(--line);
    background: var(--surface);
}

.usecase__title {
    margin: 0 0 var(--space-2);
    font-size: .9375rem;
    font-weight: 650;
    color: var(--text);
}

.usecase__body { margin: 0; font-size: .875rem; color: var(--text-secondary); }

/* ----------------------------------------------------------- Split feature */

.split {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: var(--space-12);
    align-items: center;
}

.split__title { font-size: clamp(1.5rem, 2.8vw, 2rem); margin-bottom: var(--space-4); }
.split__body { color: var(--text-secondary); font-size: 1.0625rem; }

.checklist {
    display: grid;
    gap: var(--space-3);
    margin: var(--space-6) 0 0;
    padding: 0;
    list-style: none;
}

.checklist li {
    display: grid;
    grid-template-columns: 20px minmax(0, 1fr);
    gap: var(--space-3);
    font-size: .9375rem;
    color: var(--ink-700);
}

.checklist svg { width: 20px; height: 20px; color: var(--success-fg); }

/* A panel of terminal-ish facts, for the "under the hood" half of a split. */
.spec-panel {
    padding: var(--space-6);
    border-radius: var(--radius-lg);
    border: 1px solid var(--line);
    background: var(--bg-subtle);
    box-shadow: var(--shadow-sm);
}

.spec-panel__title {
    margin: 0 0 var(--space-4);
    font-size: .6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .1em;
    color: var(--text-muted);
}

.spec-list { margin: 0; display: grid; gap: var(--space-3); }

.spec-list > div {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--space-4);
    padding-bottom: var(--space-3);
    border-bottom: 1px dashed var(--line);
}

.spec-list > div:last-child { border-bottom: 0; padding-bottom: 0; }
.spec-list dt { font-size: .875rem; color: var(--text-secondary); }

.spec-list dd {
    margin: 0;
    font-family: var(--font-mono);
    font-size: .8125rem;
    font-weight: 600;
    color: var(--text);
    text-align: right;
}

/* --------------------------------------------------------- Pricing intro */

.pricing-lede {
    max-width: 46rem;
    margin: 0 auto var(--space-12);
    text-align: center;
    color: var(--text-secondary);
}

.pricing-assure {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-2) var(--space-6);
    margin: var(--space-8) 0 0;
    padding: 0;
    list-style: none;
    font-size: .875rem;
    color: var(--text-secondary);
}

.pricing-assure li { display: inline-flex; align-items: center; gap: .45rem; }
.pricing-assure svg { width: 16px; height: 16px; color: var(--success-fg); flex: none; }

/* The Free tier's card ends in a statement rather than a call to action: there
   is nothing to buy, and the honest thing to say is that they already have it. */
.plan-card__included {
    margin: 0 0 var(--space-3);
    font-size: .875rem;
    line-height: 1.55;
    color: var(--text-secondary);
}

/* ==========================================================================
   Processing time — the customer's usage page
   ==========================================================================

   Built on the same tokens as .licence-card so the two account screens read as
   one product. The meter's three states are shared with the admin panel and the
   desktop app on purpose: a customer reading their usage to support, and the
   administrator reading the answer, should be looking at the same picture. */

.usage-card {
    position: relative;
    overflow: hidden;
    margin-bottom: var(--space-6);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-md);
}

/* The state of the meter, said once along the top edge. Three pixels of colour
   is enough to sort a stack of licences at a glance; the figures inside say the
   same thing in words for anyone the colour does not reach. */
.usage-card::before {
    content: "";
    position: absolute;
    inset: 0 0 auto;
    height: 3px;
    background: var(--grad-duo);
}

.usage-card--high::before { background: linear-gradient(90deg, var(--warning-fg), var(--p-amber-400)); }
.usage-card--spent::before { background: linear-gradient(90deg, var(--danger-fg), var(--p-red-600)); }

.usage-card__head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-4);
    flex-wrap: wrap;
    padding: var(--space-6);
    border-bottom: 1px solid var(--line);
    background: var(--bg-subtle);
}

.usage-card__plan {
    margin: 0;
    font-size: 1.0625rem;
    font-weight: 650;
    letter-spacing: -.015em;
    color: var(--text);
}

.usage-card__key {
    margin: var(--space-1) 0 0;
    font-size: .8125rem;
    color: var(--text-muted);
}

.usage-card__key code {
    padding: 0;
    background: none;
    font-family: var(--font-mono);
    letter-spacing: .08em;
}

/* --------------------------------------------------------------- The meter */

.usage-meter {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-8);
    flex-wrap: wrap;
    padding: var(--space-8) var(--space-6) var(--space-6);
}

.usage-meter__figure { flex: 1 1 16rem; min-width: 0; }

.usage-card__headline {
    margin: 0;
    font-size: clamp(2rem, 5vw, 2.75rem);
    font-weight: 700;
    letter-spacing: -.035em;
    line-height: 1.05;
    color: var(--text);
}

/* Out of time is the one state worth colouring the number for — it is the only
   one where the next thing the reader does changes. */
.usage-card__headline.is-spent { color: var(--danger-fg); }

.usage-card__sub {
    margin: var(--space-2) 0 0;
    font-size: .9375rem;
    color: var(--text-secondary);
}

.usage-card__granted { color: var(--text-muted); }

/*
  The dial.

  A conic gradient over a disc, with the surface punched back out of the middle
  — no SVG, no script, and it inherits the theme because both halves are tokens.
  It repeats the percentage the bar below already carries, deliberately: the bar
  answers "how far along", the dial answers "is this a problem", and people read
  those two at different distances.
*/
.usage-dial {
    position: relative;
    display: grid;
    place-content: center;
    justify-items: center;
    flex: none;
    width: 116px;
    height: 116px;
    border-radius: 50%;
    background: conic-gradient(var(--dial, var(--accent)) calc(var(--pct, 0) * 1%), var(--bg-inset) 0);
}

.usage-dial::after {
    content: "";
    position: absolute;
    inset: 11px;
    border-radius: 50%;
    background: var(--surface);
}

.usage-dial > * { position: relative; z-index: 1; }

.usage-dial.is-high { --dial: var(--warning-fg); }
.usage-dial.is-full { --dial: var(--danger-fg); }

.usage-dial__value {
    font-size: 1.375rem;
    font-weight: 700;
    letter-spacing: -.03em;
    line-height: 1;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

.usage-dial__label {
    margin-top: 2px;
    font-size: .6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .09em;
    color: var(--text-muted);
}

/* Unmetered plans have no proportion to draw, so they get the infinity mark
   rather than a ring stuck at nought. */
.usage-dial--open { background: var(--accent-soft); border: 1px solid var(--accent-line); }
.usage-dial--open::after { inset: 0; background: none; }
.usage-dial--open svg { width: 34px; height: 34px; color: var(--accent); }

.usage-bar {
    height: .5rem;
    margin: 0 var(--space-6);
    background: var(--bg-inset);
    border-radius: var(--radius-pill);
    overflow: hidden;
}

.usage-bar__fill {
    height: 100%;
    background: var(--grad-brand);
    border-radius: var(--radius-pill);
    transition: width 400ms var(--ease-out);
}

.usage-bar__fill.is-high { background: var(--warning-fg); }
.usage-bar__fill.is-full { background: var(--danger-fg); }

.usage-card__foot {
    margin: var(--space-3) 0 0;
    padding: 0 var(--space-6) var(--space-6);
    font-size: .8125rem;
    color: var(--text-muted);
}

.usage-card__alert {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
    margin: 0 var(--space-6) var(--space-6);
    padding: var(--space-4);
    background: var(--warning-bg);
    border: 1px solid var(--warning-line);
    border-radius: var(--radius-lg);
}

.usage-card__alert p {
    margin: 0;
    font-size: .875rem;
    line-height: 1.55;
    color: var(--text-secondary);
    max-width: 52ch;
}

/* ----------------------------------------------------- Blocks under the meter */

.usage-block {
    padding: var(--space-6);
    border-top: 1px solid var(--line);
}

.usage-block__title {
    margin: 0 0 var(--space-4);
    font-size: .6875rem;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--text-muted);
}

/*
  What used the hours.

  A figure alone makes you compare four numbers by reading them; the track
  turns that into one glance. It is proportional to the largest row rather than
  to the allowance, because the question here is "which tool cost me the most",
  not "how much of my month is gone" — the meter above already answered that.
*/
.usage-breakdown {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: var(--space-3);
}

.usage-breakdown li {
    display: grid;
    grid-template-columns: minmax(7rem, 1fr) minmax(3rem, 1.4fr) auto;
    align-items: center;
    gap: var(--space-4);
    font-size: .875rem;
}

.usage-breakdown__name { color: var(--text-secondary); }

.usage-breakdown__track {
    height: .375rem;
    border-radius: var(--radius-pill);
    background: var(--bg-inset);
    overflow: hidden;
}

.usage-breakdown__track span {
    display: block;
    height: 100%;
    border-radius: var(--radius-pill);
    background: var(--accent);
    opacity: .8;
}

.usage-breakdown__value {
    color: var(--text);
    font-weight: 600;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

@media (max-width: 620px) {
    .usage-breakdown li { grid-template-columns: minmax(0, 1fr) auto; }
    .usage-breakdown__track { display: none; }
}

.usage-history {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: var(--space-2);
}

.usage-history li {
    display: flex;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    background: var(--bg-subtle);
    font-size: .875rem;
    color: var(--text-secondary);
}

.usage-history li span:last-child { color: var(--text); font-variant-numeric: tabular-nums; }

/* Wide content scrolls inside its own box rather than pushing the page sideways. */
.table-scroll { overflow-x: auto; }

.table--compact {
    width: 100%;
    border-collapse: collapse;
    font-size: .875rem;
}

.table--compact th,
.table--compact td {
    padding: var(--space-3);
    text-align: left;
    border-bottom: 1px solid var(--line);
    vertical-align: top;
    color: var(--text-secondary);
}

.table--compact tbody tr:last-child td { border-bottom: 0; }

.table--compact th {
    font-weight: 700;
    color: var(--text-muted);
    font-size: .6875rem;
    text-transform: uppercase;
    letter-spacing: .09em;
}

.table--compact td:last-child { color: var(--text); font-variant-numeric: tabular-nums; }

.usage-note {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: var(--space-6);
    padding: var(--space-8);
    background: var(--bg-subtle);
    border: 1px solid var(--line);
    border-radius: var(--radius-xl);
}

.usage-note h3 {
    grid-column: 1 / -1;
    margin: 0;
    font-size: 1.0625rem;
}

.usage-note p {
    margin: 0;
    font-size: .875rem;
    line-height: 1.6;
    color: var(--text-secondary);
    max-width: none;
}

.usage-note strong { color: var(--text); }

/* A footnote under the usage cards: licences that exist but have no current
   allowance. Quiet on purpose — it explains an absence rather than announcing
   a problem, and the Licences page is where the detail lives. */
.usage-inactive-note {
    margin: 0 0 var(--space-6);
    font-size: .875rem;
    color: var(--text-muted);
}


/* ==========================================================================
   Landing page — motion and the components only it uses

   Everything in this block is additive. Nothing here restyles a component
   another page depends on, which is why it sits at the end of the file rather
   than being threaded through the sections above.
   ========================================================================== */

/* ------------------------------------------------------------ Reveal ----- */

/*
  Sections arrive as you reach them.

  Guarded on `.js`, which the layout's head script adds before first paint.
  That is the whole safety mechanism: with JavaScript unavailable the class
  never appears, these rules never apply, and the page renders in full. Hiding
  by default and revealing with script would turn a blocked script into a blank
  page, which is a trade nobody should take for an animation.
*/
.js [data-reveal] {
    opacity: 0;
    transform: translateY(20px);
    transition: opacity .65s var(--ease-out), transform .65s var(--ease-out);
}

.js [data-reveal].is-revealed {
    opacity: 1;
    transform: none;
}

/*
  Reduced motion is honoured twice — here and in site.js — on purpose.

  The script reveals everything immediately, and this makes sure that even the
  frame before it runs is a finished one. A visitor who has asked their system
  to stop moving things should never see the start of the animation, let alone
  a slower version of it.
*/
@media (prefers-reduced-motion: reduce) {
    .js [data-reveal] {
        opacity: 1;
        transform: none;
        transition: none;
    }

    .js .wave span,
    .js .app-stage__playhead,
    .js .app-stage__runbar span,
    .js .app-tick.is-on,
    .marquee__track,
    .chain__step::after {
        animation: none !important;
    }

    .js .app-tick.is-on { opacity: 1; }
    .app-stage__playhead { opacity: 0; }
}

/* ------------------------------------------------------ The install block */

/*
  The hero's call to action: one button and one line.

  It went through a card with a product tile, a title, a subtitle, a nested
  icon well and a two-line button label, and it was worse at every step. Four
  rows of text and two icons is not a call to action, it is a dialog — and it
  said "Windows" twice and "free" twice while it was at it.

  So the card is gone and the button IS the object. It gets the size, the light
  and the sheen; everything it needs to say beyond its own label is one quiet
  sentence underneath. The header already carries [Pricing][Download] on every
  page, so this does not need to be a second control cluster — it needs to be
  the one thing on the page that looks pressable.
*/
.get-app {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-3);
    margin-bottom: var(--space-2);
}

.btn-get {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: .7rem;
    padding: 1.05rem 1.9rem;
    font-size: 1.0625rem;
    font-weight: 660;
    letter-spacing: -.015em;
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
    color: var(--text-on-accent);
    border-radius: var(--radius-lg);
    background: var(--grad-brand);
    /* The glow is the whole treatment: a wide, soft cyan pool under the button
       and a one-pixel highlight along its top edge, which together read as a
       lit surface rather than a coloured rectangle. */
    box-shadow:
        0 18px 40px -12px var(--accent-glow),
        inset 0 1px 0 rgba(255, 255, 255, .42);
    overflow: hidden;
    transition: transform .2s var(--ease-out), box-shadow .2s var(--ease-out);
}

.btn-get svg { width: 20px; height: 20px; flex: none; }

.btn-get:hover {
    color: var(--text-on-accent);
    transform: translateY(-2px);
    box-shadow:
        0 26px 52px -12px var(--accent-glow),
        inset 0 1px 0 rgba(255, 255, 255, .55);
}

.btn-get:active { transform: translateY(0); }

/*
  A specular sweep across the face.

  It runs once, a beat after the page settles, and again on hover. Once —
  because its job is to say "this is the thing to press" on arrival, and a
  button that glints every three seconds forever is one people learn to stop
  seeing.
*/
.btn-get__sheen {
    position: absolute;
    top: -60%;
    bottom: -60%;
    left: 0;
    width: 26%;
    transform: skewX(-18deg) translateX(-320%);
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .5), transparent);
    pointer-events: none;
}

.js .btn-get__sheen { animation: sheen 1.15s var(--ease-out) 1.4s 1; }

.btn-get:hover .btn-get__sheen { animation: sheen .85s var(--ease-out) 1; }

@keyframes sheen {
    from { transform: skewX(-18deg) translateX(-320%); }
    to   { transform: skewX(-18deg) translateX(560%); }
}

/* The one supporting line. Everything the old card said in four rows, in a
   sentence — and the secondary action as a link rather than a second button. */
.get-app__fine {
    /* Wide enough to hold the sentence on one line. Wrapped, the two orphaned
       words under a big button read as an accident. */
    max-width: 62ch;
    margin: 0;
    font-size: .8125rem;
    line-height: 1.55;
    color: var(--text-muted);
}

.get-app__fine a {
    color: var(--accent-text);
    text-decoration: none;
    border-bottom: 1px solid var(--accent-line);
    white-space: nowrap;
}

.get-app__fine a:hover { border-bottom-color: currentColor; }

@media (max-width: 480px) {
    .get-app { align-items: stretch; }
    .btn-get { justify-content: center; padding: .95rem 1.2rem; font-size: 1rem; }
}

@media (prefers-reduced-motion: reduce) {
    .js .btn-get__sheen,
    .btn-get:hover .btn-get__sheen { animation: none; }
    .btn-get:hover { transform: none; }
}

/* ------------------------------------------------------- Hero ambience --- */

/*
  A cyan light source that follows the cursor.

  It is the same idea as the app's fixed corner glow, made responsive to the
  one thing a web page has that a desktop window does not: a pointer that
  belongs to the page. site.js writes the two custom properties at most once a
  frame and only on a fine pointer — there is nothing to follow on a phone, and
  the defaults below put the light in the top right where the product shot is.
*/
.hero--refine::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background: radial-gradient(
        26rem 20rem at var(--pointer-x, 76%) var(--pointer-y, 16%),
        rgba(34, 211, 238, .11),
        transparent 68%
    );
}

/* The copy and the shot sit above the light, not under it. Both are already
   positioned; only the order needed stating. */
.hero--refine .hero__inner { z-index: 1; }

.hero--refine {
    padding-bottom: 0;
}

/* --------------------------------------------------------- Format strip -- */

/*
  What it reads and what it writes, moving slowly along the foot of the hero.

  The track holds the list twice and travels exactly half its own width, which
  is what makes the loop seamless — at -50% the second copy is sitting precisely
  where the first one started, so there is no frame where the strip jumps.
*/
.marquee {
    position: relative;
    z-index: 1;
    margin-top: var(--space-12);
    padding: var(--space-4) 0;
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    overflow: hidden;
    /* Faded at both ends so the strip reads as continuing past the viewport
       rather than being cut off by it. */
    mask-image: linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
    -webkit-mask-image: linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
}

.marquee__track {
    display: flex;
    gap: var(--space-8);
    width: max-content;
    animation: marquee 46s linear infinite;
}

.marquee__track span {
    font-family: var(--font-mono);
    font-size: .75rem;
    font-weight: 500;
    letter-spacing: .12em;
    color: var(--text-muted);
    opacity: .7;
    white-space: nowrap;
}

@keyframes marquee {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}

/* --------------------------------------------------------- The chain ----- */

/*
  Five tools drawn as what they are: one pipeline, in a fixed order.

  A grid rather than a flex row, because the connectors are drawn between
  columns and a wrapping flex row would leave a line pointing at nothing. Below
  the breakpoint it becomes a single column and the connectors turn vertical,
  which is the same statement rotated rather than a different one.
*/
.chain {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: var(--space-4);
    margin: 0;
    padding: 0;
    list-style: none;
    counter-reset: chain;
}

.chain__step {
    position: relative;
    padding: var(--space-6) var(--space-4);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    text-align: center;
    transition: border-color .25s var(--ease), transform .25s var(--ease);
}

.chain__step:hover {
    border-color: var(--accent-line);
    transform: translateY(-3px);
}

/*
  The connector, and the pulse that travels along it.

  Drawn from each card towards the next and suppressed on the last, so the
  sequence never dangles off the end of the row. The dot animation is staggered
  a beat per step, which is what turns five separate lines into one signal
  moving left to right — the chain running, at the speed the copy claims it
  runs in.
*/
.chain__step::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 100%;
    width: var(--space-4);
    height: 2px;
    background: linear-gradient(to right, var(--accent-line), transparent);
    animation: chain-pulse 3.4s var(--ease-app) infinite;
}

.chain__step:last-child::after { display: none; }

.chain__step:nth-child(1)::after { animation-delay: 0s; }
.chain__step:nth-child(2)::after { animation-delay: .34s; }
.chain__step:nth-child(3)::after { animation-delay: .68s; }
.chain__step:nth-child(4)::after { animation-delay: 1.02s; }

@keyframes chain-pulse {
    0%, 100% { opacity: .35; }
    22%      { opacity: 1; }
}

.chain__icon {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    margin: 0 auto var(--space-4);
    border-radius: var(--radius-md);
    color: var(--accent-text);
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
}

.chain__icon svg { width: 22px; height: 22px; display: block; }

.chain__step:hover .chain__icon {
    color: var(--text-on-accent);
    background: var(--accent);
    border-color: transparent;
    box-shadow: 0 0 24px -4px var(--accent-glow);
}

/* Numbered from the list rather than from markup, so reordering the steps
   renumbers them and nobody has to remember to. */
.chain__title {
    margin: 0 0 var(--space-2);
    font-size: 1rem;
}

.chain__title::before {
    counter-increment: chain;
    content: counter(chain) ". ";
    color: var(--text-muted);
    font-weight: 600;
}

.chain__body {
    margin: 0;
    font-size: .8125rem;
    line-height: 1.6;
    color: var(--text-secondary);
}

/* Centred as a block with an inline icon, not as a flex row.

   As a flex row the sentence became one wide anonymous item and the icon was
   pushed to the far left of the container while the text centred itself inside
   what was left — which looks like a bullet that lost its list. */
.chain__note {
    display: block;
    max-width: 62ch;
    margin: var(--space-8) auto 0;
    font-size: .9375rem;
    color: var(--text-secondary);
    text-align: center;
}

.chain__note svg {
    width: 18px;
    height: 18px;
    vertical-align: -.24em;
    margin-right: .4rem;
    color: var(--success-fg);
}

@media (max-width: 1080px) {
    .chain { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    /* With three across, the connector on every third card points into the gutter. */
    .chain__step:nth-child(3n)::after { display: none; }
}

@media (max-width: 700px) {
    .chain { grid-template-columns: minmax(0, 1fr); }
    .chain__step { text-align: left; padding: var(--space-4); }
    .chain__icon { margin: 0 0 var(--space-3); }

    /* The pipeline turns vertical rather than disappearing. */
    .chain__step::after,
    .chain__step:nth-child(3n)::after {
        display: block;
        top: 100%;
        left: 50%;
        width: 2px;
        height: var(--space-4);
        background: linear-gradient(to bottom, var(--accent-line), transparent);
    }

    .chain__step:last-child::after { display: none; }
}

/* -------------------------------------------------------- Group labels --- */

/*
  The divider between the audio tools and the video ones.

  It carries the app's own convention into the site: audio is cyan, video is
  violet, and the two are never the same colour anywhere in the product. That
  is the entire job of the second accent — it says "different kind of work"
  without a word being spent on it.
*/
.group-label {
    display: flex;
    align-items: center;
    gap: .625rem;
    margin: 0 0 var(--space-6);
    /* It is a <p>, and the base rule caps every paragraph at the reading
       measure. That is right for prose and wrong for a rule that is supposed
       to run the width of the grid beneath it — at 68ch the line stopped
       halfway across and read as a mistake. */
    max-width: none;
    font-size: .8125rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .14em;
    color: var(--accent-text);
}

.group-label::after {
    content: "";
    flex: 1;
    height: 1px;
    background: linear-gradient(to right, var(--accent-line), transparent);
}

.group-label__dot {
    width: 8px;
    height: 8px;
    flex: none;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 12px var(--accent-glow);
}

.group-label--video {
    margin-top: var(--space-12);
    color: var(--violet-text);
}

.group-label--video::after { background: linear-gradient(to right, var(--violet-line), transparent); }
.group-label--video .group-label__dot {
    background: var(--violet);
    box-shadow: 0 0 12px var(--violet-soft);
}

/* -------------------------------------------------------- Feature cards -- */

/* Three tools, three columns, held even — `auto-fit` would stretch the last
   card across a whole row on a wide screen and make three tools look like a
   list that ran out. */
.feature-grid--three {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

@media (max-width: 900px) {
    .feature-grid--three { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
}

/* The video variant of a feature card. Only the accent moves; the card is
   otherwise identical, which is what keeps the two groups reading as one
   product rather than two. */
.feature--video .feature__icon {
    color: var(--violet-text);
    background: var(--violet-soft);
    border-color: var(--violet-line);
}

.feature--video:hover { border-color: var(--violet-line); }

/* A cyan edge that lights along the top of a card on hover. One pseudo-element,
   no layout, and it gives forty-odd cards a shared behaviour that reads as the
   accent responding rather than as a border colour changing. */
.feature::before {
    content: "";
    position: absolute;
    top: -1px;
    left: 12%;
    right: 12%;
    height: 1px;
    background: linear-gradient(to right, transparent, var(--accent), transparent);
    opacity: 0;
    transition: opacity .25s var(--ease);
}

.feature--video::before { background: linear-gradient(to right, transparent, var(--violet), transparent); }

.feature:hover::before { opacity: 1; }

/* --------------------------------------------------- Emphasis in titles -- */

/* A section heading occasionally needs one word carrying the accent. Kept flat
   rather than gradient-filled: the hero owns the gradient, and a page where
   four headings glow is a page where the hero stops being the loudest thing
   on it. */
.section__title em {
    font-style: normal;
    color: var(--accent-text);
}

/* ==========================================================================
   Landing page — the before/after demonstration, and what sits around it

   Everything in this block is additive. Nothing here restyles a component
   another page depends on.
   ========================================================================== */

/* ------------------------------------------------ Hero reassurance row --- */

/*
  Three short guarantees under the download tile.

  The tile answers "what do I get"; this answers "what will it cost me to find
  out", which is the question that actually stops somebody pressing it. Kept to
  three items and one line each — a fourth turns a reassurance into a spec
  sheet.
*/
.hero__assure {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-6);
    margin: var(--space-6) 0 0;
    padding: 0;
    list-style: none;
}

.hero__assure li {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    font-size: .8125rem;
    font-weight: 550;
    color: var(--text-secondary);
}

.hero__assure svg { width: 15px; height: 15px; flex: none; color: var(--success-fg); }

/* ------------------------------------------------ Drag-to-compare panel -- */

/*
  The comparison, at a size you can actually read.

  The hero's version is a thumbnail with two buttons; this is the same signal
  across the full width of the page with a handle you drag through it. That
  matters because the claim being made is spatial — the peaks survive and the
  space between them does not — and a spatial claim shown as two alternating
  states makes the reader hold one of them in memory to compare against.

  THE DRAG HANDLE IS AN <input type="range">.

  Not a pointerdown implementation with a touch fallback bolted on. A range
  input already drags with a mouse, drags with a finger, moves with the arrow
  keys, and announces itself with a value. Writing that by hand is forty lines
  to arrive back where the platform started, and the hand-written version is
  the one that stops working on a device nobody tested.

  With JavaScript unavailable the handle does nothing and the panel sits at its
  default 50% — which is still both halves of the comparison, side by side.
*/
.split-demo {
    --split: 50;

    margin: 0;
    padding: var(--space-6);
    background: var(--p-panel);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-lg);
}

/* Obsidian in both themes, like the hero's app shot: this is a picture OF the
   application, and a waveform on white is a picture of something else. */
:root[data-theme="light"] .split-demo {
    background: var(--p-panel);
    border-color: rgba(255, 255, 255, .12);
}

.split-demo__stage {
    position: relative;
    height: clamp(170px, 26vw, 260px);
    border-radius: var(--radius-lg);
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .025), transparent 55%),
        var(--p-obsidian);
    border: 1px solid rgba(255, 255, 255, .07);
    overflow: hidden;
    touch-action: pan-y;
}

.split-demo__wave {
    position: absolute;
    inset: var(--space-8) var(--space-4) var(--space-4);
    display: flex;
    align-items: center;
    gap: 1px;
}

.split-demo__wave span {
    flex: 1 1 0;
    min-width: 0;
    height: var(--h);
    border-radius: 2px;
}

.split-demo__wave--raw span { background: #3b4553; }

.split-demo__wave--clean span {
    background: linear-gradient(180deg, var(--p-cyan-300), var(--p-cyan-500));
    box-shadow: 0 0 10px rgba(34, 211, 238, .3);
}

/*
  The refined half, revealed from the handle rightwards.

  clip-path rather than a width, so both rows keep the same bar positions. A
  narrowed flex row would squeeze its own bars and the two signals would stop
  lining up — which is the one thing this panel must not do, because "same
  recording, different treatment" is the entire claim.
*/
.split-demo__clip {
    position: absolute;
    inset: 0;
    clip-path: inset(0 0 0 calc(var(--split) * 1%));
}

.split-demo__seam {
    position: absolute;
    top: 0;
    bottom: 0;
    left: calc(var(--split) * 1%);
    width: 2px;
    margin-left: -1px;
    background: var(--p-cyan-300);
    box-shadow: 0 0 18px 2px rgba(34, 211, 238, .45);
    pointer-events: none;
}

.split-demo__seam::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 34px;
    height: 34px;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: var(--p-cyan-400);
    border: 2px solid var(--p-obsidian);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .5);
}

/* The grip on the knob: a chevron pair drawn with borders, so the control needs
   no image and no second element. */
.split-demo__seam::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 1;
    width: 9px;
    height: 9px;
    transform: translate(-50%, -50%) rotate(45deg);
    border: 2px solid var(--p-cyan-ink);
    border-top: 0;
    border-left: 0;
    border-radius: 1px;
    box-shadow: -7px -7px 0 -2px var(--p-cyan-ink);
}

/* The real control: transparent, stretched over the whole stage. */
.split-demo__range {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    background: transparent;
    border: 0;
    appearance: none;
    -webkit-appearance: none;
    cursor: ew-resize;
}

.split-demo__range::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 40px;
    height: 260px;
    background: transparent;
    cursor: ew-resize;
}

.split-demo__range::-moz-range-thumb {
    width: 40px;
    height: 260px;
    background: transparent;
    border: 0;
    cursor: ew-resize;
}

.split-demo__range:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.split-demo__tag {
    position: absolute;
    top: var(--space-3);
    padding: .2rem .6rem;
    border-radius: var(--radius-pill);
    font-size: .625rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .1em;
    pointer-events: none;
    z-index: 2;
}

.split-demo__tag--raw {
    left: var(--space-3);
    color: #8a94a5;
    background: rgba(255, 255, 255, .06);
}

.split-demo__tag--clean {
    right: var(--space-3);
    color: var(--p-cyan-ink);
    background: var(--p-cyan-400);
}

/* The figures under the stage. Both readings are printed at once rather than
   swapped by the handle: this is the one panel where the two states are meant
   to be legible together. */
.split-demo__readout {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: var(--space-3);
    margin: var(--space-4) 0 0;
    padding: 0;
}

.split-demo__readout > div {
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    background: rgba(255, 255, 255, .03);
    border: 1px solid rgba(255, 255, 255, .07);
}

.split-demo__readout dt {
    font-size: .625rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .09em;
    color: #5c6675;
}

.split-demo__readout dd {
    display: flex;
    align-items: baseline;
    gap: .4rem;
    margin: var(--space-1) 0 0;
    font-size: .875rem;
    font-weight: 640;
    color: #8a94a5;
    font-variant-numeric: tabular-nums;
}

.split-demo__readout dd b { font-weight: 700; color: var(--p-cyan-300); }
.split-demo__readout dd i { font-style: normal; color: #5c6675; }

.split-demo__hint {
    margin: var(--space-4) auto 0;
    max-width: none;
    text-align: center;
    font-size: .8125rem;
    color: var(--text-muted);
}

/* ------------------------------------------------------------ Use cases -- */

.usecase__icon {
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    margin-bottom: var(--space-4);
    border-radius: var(--radius-md);
    color: var(--accent-text);
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
}

.usecase__icon svg { width: 18px; height: 18px; }

.usecase__gain {
    display: block;
    margin-top: var(--space-4);
    padding-top: var(--space-3);
    border-top: 1px solid var(--line);
    font-size: .8125rem;
    font-weight: 600;
    color: var(--accent-text);
}

/* ---------------------------------------------------------------- Proof -- */

/*
  The slot a competitor fills with testimonials.

  There are none here that anybody could verify, and a page that invents them
  is a page where the one unverifiable claim sits next to seven true ones. So
  the slot argues the opposite case: the software runs on a real file, at full
  quality, before any money changes hands — which is a stronger proof than a
  quotation with a stock photograph beside it.
*/
.proof-band {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: var(--space-12);
    align-items: center;
    padding: var(--space-12);
    background: var(--grad-spot), var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-md);
}

.proof-band__title {
    margin: 0 0 var(--space-4);
    font-size: clamp(1.5rem, 2.8vw, 2rem);
    letter-spacing: -.03em;
}

.proof-band__body { margin: 0 0 var(--space-6); color: var(--text-secondary); }

.proof-band__list {
    display: grid;
    gap: var(--space-4);
    margin: 0;
    padding: 0;
    list-style: none;
}

.proof-band__list li {
    display: grid;
    grid-template-columns: 40px minmax(0, 1fr);
    gap: var(--space-4);
    align-items: start;
}

.proof-band__list svg {
    width: 40px;
    height: 40px;
    padding: 9px;
    border-radius: var(--radius-md);
    color: var(--accent-text);
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
}

.proof-band__list strong { display: block; color: var(--text); font-size: .9375rem; }
.proof-band__list span { font-size: .875rem; color: var(--text-secondary); }

@media (max-width: 720px) {
    .proof-band { padding: var(--space-6); gap: var(--space-8); }
    .split-demo { padding: var(--space-4); }
}

/* ==========================================================================
   Violet finishing touches

   Third in the order, after obsidian and cyan, and deliberately small: an
   edge, a corner, one glyph. Every rule here is a few pixels of colour on
   something that is already doing its job in cyan or grey.

   The test each one has to pass: cover it with your thumb and the page still
   works. If removing it would break something, it is not a finishing touch and
   it does not belong in this block.
   ========================================================================== */

/*
  The account band's bottom edge.

  A flat 1px line ran the width of the page and read as a table rule. It now
  fades cyan into violet and out again — the same duo the brand gradient uses,
  at one pixel, so it reads as a seam between two surfaces rather than a border
  drawn around one.
*/
.account-shell {
    border-bottom: 0;
    position: relative;
}

.account-shell::after {
    content: "";
    position: absolute;
    inset: auto 0 0;
    height: 1px;
    background: linear-gradient(
        to right,
        transparent,
        var(--accent-line) 18%,
        var(--violet-line) 52%,
        transparent 86%
    );
}

/* The avatar keeps its cyan face and gains a violet edge underneath, so the one
   personal element on the band is the one place both accents meet. */
.account-head__avatar {
    box-shadow: var(--shadow-accent), 0 0 0 1px var(--violet-line);
}

/*
  The licence spotlight.

  The card that matters most on the overview, so it gets the one violet corner
  on the screen — a soft bloom in the top-right, opposite the key. Sized in the
  card's own corner rather than across it, which is what keeps it from becoming
  another wash.
*/
.spotlight::after {
    content: "";
    position: absolute;
    top: -3rem;
    right: -3rem;
    width: 14rem;
    height: 10rem;
    border-radius: 50%;
    background: radial-gradient(closest-side, var(--violet-soft), transparent 78%);
    pointer-events: none;
}

.spotlight > * { position: relative; z-index: 1; }

/* Tab pills: violet only on the one you are standing on, as a hairline under
   the cyan tint. Two accents on one control, neither shouting. */
.account-nav a.is-current {
    box-shadow: inset 0 -2px 0 -1px var(--violet-line);
}

/* The usage dial's track picks up the faintest violet, so the spent arc reads
   against something warmer than flat grey. */
.usage-dial {
    background: conic-gradient(
        var(--dial, var(--accent)) calc(var(--pct, 0) * 1%),
        var(--violet-soft) 0
    );
}

/* Licence and usage cards: the top rule already carries the duo gradient. This
   just lets the violet end of it survive on the inactive states, which would
   otherwise lose the second accent entirely. */
.licence-card--inactive::before {
    background: linear-gradient(90deg, var(--warning-fg), var(--p-violet-500));
}

/* Key blocks: a violet left edge. The key is the one string on the page people
   came to copy, and this marks it without adding another filled panel. */
.licence-key-row {
    border-left: 2px solid var(--violet-line);
}

/* Stat tiles alternate their icon tile between the two accents already. The
   violet one gains a matching value colour on hover, so the pairing reads as
   deliberate rather than as one tile being different. */
.tile--violet:hover .tile__note { color: var(--violet-text); }

/* Empty states: the dashed border goes violet. They are the quietest screens
   in the account area and the one place a little colour is welcome. */
.empty-state { border-color: var(--violet-line); }

/* The primary button keeps its cyan face and gains a violet underglow — visible
   only on hover, and only as light bleeding out from beneath the edge. */
.btn--primary:hover {
    box-shadow: 0 10px 30px var(--accent-glow), 0 6px 18px -8px var(--violet-line);
}

/*
  Section kickers.

  The small uppercase label above a heading was cyan on every section, which
  made nine of them and stopped meaning anything. The dot before it is violet
  now: same label, one point of difference, and it gives the eye something to
  land on down a long page.
*/
.kicker::before {
    content: "";
    display: inline-block;
    width: 5px;
    height: 5px;
    margin-right: .55rem;
    border-radius: 50%;
    background: var(--violet);
    vertical-align: middle;
    box-shadow: 0 0 8px var(--violet-line);
}

/* The footer's top edge, matching the account band's seam so the page opens and
   closes on the same detail. */
.site-footer {
    position: relative;
}

.site-footer::before {
    content: "";
    position: absolute;
    inset: 0 0 auto;
    height: 1px;
    background: linear-gradient(
        to right,
        transparent,
        var(--violet-line) 30%,
        var(--accent-line) 64%,
        transparent 88%
    );
}

/* ==========================================================================
   Landing hero — the centred variant

   The two-column hero (copy left, app shot right) is the arrangement every
   developer-tool landing page arrives at, and it is why the page read as
   generic: the layout itself carried no information about what the product is.

   This variant stacks instead. Headline, one line of support, one button, then
   the product across the full width underneath — which gives the app shot
   about 60% more room than a half-column did, and the app shot is the only
   thing on the page that shows what you actually get.

   Additive: `.hero--stack` opts in, so the two-column version stays intact for
   any page still using it.
   ========================================================================== */

.hero--stack .hero__inner {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-12);
    text-align: center;
}

.hero--stack .hero__copy {
    max-width: 56rem;
    margin-inline: auto;
}

.hero--stack .hero__lede { margin-inline: auto; }
.hero--stack .get-app { align-items: center; }
.hero--stack .hero__assure { justify-content: center; }
.hero--stack .eyebrow { justify-content: center; }

/* The app shot loses its rotation here. A tilted panel works when it sits
   beside the copy and leans into it; centred and full width it just looks
   crooked. */
.hero--stack .app-shot { transform: none; }
.hero--stack .hero__visual { perspective: none; }

/*
  The headline, with the tools set into it.

  This is the one piece taken from the reference, and it earns its place: the
  chips put the actual verbs of the product inside the sentence that claims
  them, so the headline stops being a slogan and starts being a list of what
  the software does. Ours use the app's own tool glyphs rather than emoji, so
  they are the same marks that appear in the rail of the application.
*/
.hero__title--chips {
    font-size: clamp(2rem, 5.6vw, 3.75rem);
    line-height: 1.16;
    letter-spacing: -.04em;
    font-weight: 640;
}

.title-chip {
    display: inline-grid;
    place-items: center;
    width: .95em;
    height: .95em;
    margin-right: .12em;
    vertical-align: -.14em;
    border-radius: .26em;
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
    color: var(--accent-text);
}

.title-chip svg { width: .58em; height: .58em; }

/* The second chip takes violet, so the pair reads as the audio/video split the
   whole product is organised around rather than as decoration. */
.title-chip--alt {
    background: var(--violet-soft);
    border-color: var(--violet-line);
    color: var(--violet-text);
}

/*
  One word in a serif italic.

  A single contrasting face in a headline is the cheapest way to make type look
  set rather than defaulted, and it lands on the phrase that carries the claim.
  The stack ends in a real serif on every platform we ship to, so there is no
  webfont and no flash.
*/
.hero__title em,
.section__title em.serif {
    font-family: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia,
                 "Times New Roman", serif;
    font-style: italic;
    font-weight: 500;
    letter-spacing: -.01em;
    color: var(--accent-text);
}

/*
  The strip above the headline.

  The reference puts a customer count here. We do not have one, and the note at
  the top of home.php is explicit that inventing one would be the only
  unverifiable claim on the page — so the slot carries the thing that is both
  true and the actual reason to choose this: the work happens on your machine.
*/
.hero-flag {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
    margin-bottom: var(--space-6);
    padding: .3rem .9rem .3rem .35rem;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--surface) 70%, transparent);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    font-size: .8125rem;
    color: var(--text-secondary);
}

/* Three overlapping discs where the reference has customer faces. Ours are the
   three tool glyphs, which is the honest version of the same shape: it says
   what runs, not who bought it. */
.hero-flag__marks {
    display: flex;
    flex: none;
}

.hero-flag__marks span {
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--bg-inset);
    border: 1px solid var(--line-strong);
    color: var(--accent-text);
}

.hero-flag__marks span + span { margin-left: -9px; }
.hero-flag__marks span:nth-child(2) { color: var(--violet-text); }
.hero-flag__marks span:nth-child(3) { color: var(--text-muted); }
.hero-flag__marks svg { width: 13px; height: 13px; }

.hero-flag strong { color: var(--text); font-weight: 640; }

@media (max-width: 760px) {
    .hero-flag { font-size: .75rem; }
    .hero-flag__marks span { width: 22px; height: 22px; }
}

/* ==========================================================================
   Liquid glass — the header capsule

   Real glass is not "a translucent box". Four things separate it from a tinted
   panel, and leaving any one out is what makes a blurred div still read as a
   blurred div:

   1. IT BENDS LIGHT. A backdrop blur alone averages what is behind it. Adding
      saturation and a slight brightness lift makes the colours underneath pool
      and intensify the way they do through a real lens.

   2. IT HAS AN EDGE. Glass is thick, and the thickness catches light along the
      top rim and drops shadow along the bottom one. Two inset shadows, opposite
      signs, opposite ends — this is the single biggest tell.

   3. IT HAS A SPECULAR HIGHLIGHT. A soft sheen across the upper surface where
      the light source would be, not a uniform white overlay.

   4. IT FLOATS. A contact shadow underneath, tight and dark, so the capsule
      reads as sitting above the page rather than printed onto it.

   All four are one element with pseudo-elements. No images, no script.
   ========================================================================== */

.site-header__inner {
    position: relative;
    isolation: isolate;

    /* 1 — refraction. The brightness lift is what stops the blur reading as
       frosted plastic; glass concentrates light, it does not just diffuse it. */
    backdrop-filter: blur(22px) saturate(200%) brightness(1.12);
    -webkit-backdrop-filter: blur(22px) saturate(200%) brightness(1.12);

    /* The fill is barely there. Most of what you see should be the page behind
       it, bent — not a grey panel with the page faintly visible through it. */
    background: linear-gradient(
        180deg,
        rgba(255, 255, 255, .10) 0%,
        rgba(255, 255, 255, .035) 42%,
        rgba(255, 255, 255, .015) 100%
    );

    border: 1px solid rgba(255, 255, 255, .12);

    /* 2 and 4 — the lit top rim, the shaded bottom rim, and the contact
       shadow that lifts the whole thing off the page. */
    box-shadow:
        inset 0 1px 0 0 rgba(255, 255, 255, .28),
        inset 0 -1px 0 0 rgba(0, 0, 0, .35),
        inset 0 0 24px 0 rgba(255, 255, 255, .05),
        0 10px 24px -12px rgba(0, 0, 0, .75),
        0 24px 60px -28px rgba(0, 0, 0, .9);
}

/* 3 — the specular sheen. Sits above the fill, below the content, and is
   masked to the top half so it reads as a curved surface catching light rather
   than a gradient laid over a rectangle. */
.site-header__inner::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    background: radial-gradient(
        120% 100% at 28% -30%,
        rgba(255, 255, 255, .22) 0%,
        rgba(255, 255, 255, .06) 38%,
        transparent 64%
    );
    pointer-events: none;
}

/* The faintest accent bleed along the bottom inside edge — the colour of the
   page pooling at the thickest part of the glass. This is the one place cyan
   and violet appear in the header, and at this opacity they read as light
   rather than as colour. */
.site-header__inner::after {
    content: "";
    position: absolute;
    inset: auto 12% -1px;
    height: 1px;
    z-index: -1;
    background: linear-gradient(
        to right,
        transparent,
        var(--accent-line) 35%,
        var(--violet-line) 68%,
        transparent
    );
    opacity: .5;
    pointer-events: none;
}

/* Scrolled: the glass thickens rather than turning into a solid bar. More fill,
   a deeper contact shadow, a brighter top rim. */
.site-header.is-stuck .site-header__inner {
    background: linear-gradient(
        180deg,
        rgba(255, 255, 255, .13) 0%,
        rgba(255, 255, 255, .05) 42%,
        rgba(255, 255, 255, .02) 100%
    );
    border-color: rgba(255, 255, 255, .16);
    box-shadow:
        inset 0 1px 0 0 rgba(255, 255, 255, .34),
        inset 0 -1px 0 0 rgba(0, 0, 0, .4),
        inset 0 0 24px 0 rgba(255, 255, 255, .06),
        0 12px 28px -12px rgba(0, 0, 0, .85),
        0 30px 70px -30px rgba(0, 0, 0, .95);
}

/*
  The light theme's glass is the same construction inverted: the page behind it
  is bright, so the fill darkens instead of lightening and the rim that catches
  the light is the bottom one.
*/
:root[data-theme="light"] .site-header__inner {
    backdrop-filter: blur(22px) saturate(190%) brightness(1.04);
    -webkit-backdrop-filter: blur(22px) saturate(190%) brightness(1.04);
    background: linear-gradient(
        180deg,
        rgba(255, 255, 255, .78) 0%,
        rgba(255, 255, 255, .58) 100%
    );
    border-color: rgba(255, 255, 255, .9);
    box-shadow:
        inset 0 1px 0 0 rgba(255, 255, 255, .95),
        inset 0 -1px 0 0 rgba(18, 22, 29, .06),
        0 10px 24px -14px rgba(18, 22, 29, .3),
        0 24px 50px -30px rgba(18, 22, 29, .25);
}

:root[data-theme="light"] .site-header__inner::before {
    background: radial-gradient(
        120% 100% at 28% -30%,
        rgba(255, 255, 255, .9) 0%,
        rgba(255, 255, 255, .3) 40%,
        transparent 66%
    );
}

/* Buttons inside the capsule get a matching, quieter treatment, so they read as
   sitting IN the glass rather than on top of it. */
.site-header .btn--ghost {
    background: rgba(255, 255, 255, .06);
    border-color: rgba(255, 255, 255, .12);
    box-shadow: inset 0 1px 0 0 rgba(255, 255, 255, .12);
}

.site-header .btn--ghost:hover {
    background: rgba(255, 255, 255, .11);
    border-color: rgba(255, 255, 255, .2);
}

:root[data-theme="light"] .site-header .btn--ghost {
    background: rgba(255, 255, 255, .7);
    border-color: rgba(18, 22, 29, .1);
    box-shadow: inset 0 1px 0 0 rgba(255, 255, 255, .9);
}

/*
  Reduced transparency, the accessibility setting.

  Some people get motion sick or simply cannot read text over a moving
  background. The capsule keeps its shape and loses the glass.
*/
@media (prefers-reduced-transparency: reduce) {
    .site-header__inner {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        background: var(--bg);
    }

    .site-header__inner::before,
    .site-header__inner::after { display: none; }
}

/* ==========================================================================
   The hero's side space

   Centring the headline left two tall empty columns either side of it. Empty
   space is only "breathing room" when something needs room to breathe; at this
   width it was just the page failing to start.

   Filled with three small glass cards that carry real readings from the
   product — the same figures the app shot below shows. They are placed by
   absolute position off the hero's own box, so they occupy the margin without
   narrowing the headline, and they vanish below the breakpoint where the margin
   itself no longer exists.
   ========================================================================== */

.hero--stack .hero__inner { position: relative; }

.hero-side {
    position: absolute;
    z-index: 2;
    width: 12.5rem;
    padding: var(--space-4);
    border-radius: var(--radius-lg);

    /* The same glass as the header capsule, at a smaller thickness. */
    background: linear-gradient(
        180deg,
        rgba(255, 255, 255, .08) 0%,
        rgba(255, 255, 255, .025) 100%
    );
    border: 1px solid rgba(255, 255, 255, .10);
    backdrop-filter: blur(16px) saturate(180%);
    -webkit-backdrop-filter: blur(16px) saturate(180%);
    box-shadow:
        inset 0 1px 0 0 rgba(255, 255, 255, .2),
        0 18px 40px -24px rgba(0, 0, 0, .9);
}

:root[data-theme="light"] .hero-side {
    background: linear-gradient(180deg, rgba(255, 255, 255, .8), rgba(255, 255, 255, .6));
    border-color: rgba(255, 255, 255, .9);
    box-shadow:
        inset 0 1px 0 0 rgba(255, 255, 255, .95),
        0 18px 40px -26px rgba(18, 22, 29, .35);
}

/*
  Placed off the top-left and right of the copy block, tilted a couple of
  degrees so they read as objects resting on the page rather than as two more
  boxes in the grid.
*/
.hero-side--a { top: 4.5rem;  left: 0;  transform: rotate(-2.5deg); }
.hero-side--b { top: 13rem;   right: 0; transform: rotate(2.5deg); }
.hero-side--c { top: 22.5rem; left: 1.5rem; transform: rotate(1.5deg); }

.hero-side__label {
    display: flex;
    align-items: center;
    gap: .4rem;
    margin: 0 0 var(--space-2);
    font-size: .625rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .1em;
    color: var(--text-muted);
}

.hero-side__label svg { width: 13px; height: 13px; color: var(--accent); }
.hero-side--b .hero-side__label svg { color: var(--violet); }

.hero-side__value {
    display: block;
    font-size: 1.375rem;
    font-weight: 700;
    letter-spacing: -.03em;
    line-height: 1.1;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

.hero-side__note {
    display: block;
    margin-top: 2px;
    font-size: .75rem;
    line-height: 1.4;
    color: var(--text-secondary);
}

/* A tiny meter on the middle card, so one of the three is a picture rather than
   three numbers in a column. */
.hero-side__meter {
    display: flex;
    gap: 2px;
    margin-top: var(--space-3);
    height: 22px;
    align-items: flex-end;
}

.hero-side__meter i {
    flex: 1;
    border-radius: 1px;
    background: var(--accent);
    opacity: .85;
}

.hero-side__meter i:nth-child(1) { height: 40%; }
.hero-side__meter i:nth-child(2) { height: 75%; }
.hero-side__meter i:nth-child(3) { height: 55%; }
.hero-side__meter i:nth-child(4) { height: 100%; }
.hero-side__meter i:nth-child(5) { height: 65%; }
.hero-side__meter i:nth-child(6) { height: 35%; }
.hero-side__meter i:nth-child(7) { height: 80%; }
.hero-side__meter i:nth-child(8) { height: 50%; }

/*
  Below 1200px the margin they sit in stops existing, and a floating card with
  nowhere to float lands on the headline. They go rather than reflow: their job
  is to fill space, and at this width there is none to fill.
*/
@media (max-width: 1200px) {
    .hero-side { display: none; }
}

/* Slightly inboard on the widest screens, so they stay related to the text
   instead of drifting to the window edges. */
@media (min-width: 1500px) {
    .hero-side--a { left: 3rem; }
    .hero-side--b { right: 3rem; }
    .hero-side--c { left: 4.5rem; }
}

/* ---------------------------------------------------------------------------
 * Download verification (Phase 13)
 *
 * The published SHA-256, folded away behind a summary. Collapsed by default
 * because most people click Download and leave, and a wall of hex above the
 * button would read as an error. Present at all because the installer is not
 * code-signed: this checksum is the only way a customer can tell the real build
 * from one substituted in transit, so it has to be findable by whoever thinks
 * to look.
 * ------------------------------------------------------------------------- */

.download-card__verify {
    margin-top: var(--space-3);
    text-align: left;
    font-size: .78rem;
}

.download-card__verify > summary {
    cursor: pointer;
    color: var(--text-muted);
    list-style: none;
    padding: var(--space-1) 0;
}

.download-card__verify > summary::-webkit-details-marker { display: none; }

.download-card__verify > summary::before {
    content: "▸";
    display: inline-block;
    margin-right: .4em;
    transition: transform .15s ease;
}

.download-card__verify[open] > summary::before { transform: rotate(90deg); }

.download-card__verify > summary:hover { color: var(--text); }

.download-card__hash-label {
    margin: var(--space-2) 0 var(--space-1);
    color: var(--text-muted);
    font-size: .7rem;
    letter-spacing: .06em;
    text-transform: uppercase;
}

/* Breaks anywhere: 64 hex characters do not fit a card at any sensible size. */
.download-card__hash {
    display: block;
    padding: var(--space-2);
    background: var(--surface-2, rgba(255, 255, 255, .04));
    border: 1px solid var(--line);
    border-radius: 6px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: .7rem;
    line-height: 1.5;
    color: var(--text-secondary);
    overflow-wrap: anywhere;
    word-break: break-all;
}

.download-card__hash-help {
    margin: var(--space-2) 0 0;
    color: var(--text-muted);
    line-height: 1.55;
}

.download-card__hash-help code {
    padding: .1em .35em;
    background: var(--surface-2, rgba(255, 255, 255, .04));
    border-radius: 4px;
    font-size: .95em;
    overflow-wrap: anywhere;
}
