/* =============================================================================
   Enterra - Design System & Marketing Site Stylesheet
   Derived faithfully from the EnterramonTheme design language (style.css)
   Original accent: orange #ff7a2c  →  Recoloured: Vivid Emerald #22c55e
   =============================================================================
   TABLE OF CONTENTS
   0. Fonts & Icons
   1. Design Tokens
   2. Base / Reset
   3. Typography
   4. Layout & Utilities
   5. Buttons
   6. Forms & Inputs
   7. Cards / Glass / Badges / Dividers
   8. Effects (blur-decals, glows, gradients)
   9. Header / Nav
   10. Hero
   11. Sections (trust band, features, tracks, how-it-works, pricing, FAQ)
   12. Footer
   13. Animations
   14. Responsive
   ============================================================================= */

/* =============================================================================
   0. FONTS & ICONS
   ============================================================================= */

@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=Manrope:wght@400;500;600;700&family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap');

/* -----------------------------------------------------------------------------
   DISPLAY TYPEFACE - LEAFY (self-hosted, single weight 400, WOFF)
   A decorative serif with botanical flourishes. Reserved for the hero h1
   statement only, where it pairs with the leaf logo art.
   Coverage: full basic Latin, em/en dash, curly quotes, bullet, infinity.
----------------------------------------------------------------------------- */
@font-face {
    font-family: 'Leafy';
    src: url('../fonts/Leafy-Regular.woff') format('woff');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

/* -----------------------------------------------------------------------------
   HEADING TYPEFACE - GRIFT (variable, wght 100-900)
   Carries every branded heading except the hero statement. Being a variable
   font it has real weights, so headings use 600 instead of synthetic bold.
   Coverage: full basic Latin, em/en dash, curly quotes, bullet, infinity, arrow.
----------------------------------------------------------------------------- */
@font-face {
    font-family: 'Grift';
    src: url('../fonts/Grift-Variable.woff2') format('woff2');
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
}

.material-symbols-outlined {
    font-family: 'Material Symbols Outlined' !important;
    font-weight: normal;
    font-style: normal;
    display: inline-block;
    line-height: 1;
    text-transform: none;
    letter-spacing: normal;
    word-wrap: normal;
    white-space: nowrap;
    direction: ltr;
    vertical-align: middle;
    font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}

/* =============================================================================
   1. DESIGN TOKENS
   ============================================================================= */

:root {
    /* ---- PRIMARY VIVID EMERALD ---- */
    --color-primary: #22c55e;
    --color-primary-dark: #16a34a;
    --color-primary-darker: #0a6021;
    --color-primary-light: #86efac;
    --color-primary-dim: rgba(34, 197, 94, 0.12);
    --color-primary-dim-20: rgba(34, 197, 94, 0.2);

    /* ---- NEUTRAL SURFACE ---- */
    --color-white: #ffffff;
    --color-surface: #f5f6f7;
    --color-surface-elevated: #ffffff;
    --color-surface-variant: #dadddf;
    --color-on-surface: #1b1f1c;
    --color-on-surface-variant: #545a56;
    --color-on-surface-inverse: #9b9d9e;
    --color-on-surface-muted: #6b726d;

    /* ---- DARK ALTERNATE SECTIONS ---- */
    --color-ink: #0b0f0c;
    --color-ink-soft: #121814;

    /* ---- SUPPORTING ---- */
    --color-secondary: #d9f9e1;
    --color-secondary-container: #dbe9e0;
    --color-on-secondary: #2b4a38;
    /* Referral panel green. Deeper than --color-primary-dark because white
       text on #16a34a is only 3.3:1; this reaches 5.0:1 (WCAG AA). */
    --color-panel-green: #15803d;
    --color-error: #b02500;
    --color-error-container: #f95630;

    /* ---- EFFECTS ---- */
    --color-border-glow: rgba(255, 255, 255, 0.49);
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
    --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
    --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
    --shadow-green-glow: 0 10px 30px -10px rgba(34, 197, 94, 0.4);

    /* ---- TYPOGRAPHY ---- */
    --font-headline: 'Grift', 'Plus Jakarta Sans', system-ui, sans-serif;
    --font-display: 'Leafy', 'Plus Jakarta Sans', system-ui, sans-serif;
    --font-body: 'Manrope', 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;

    /* ---- SPACING (8px base) ---- */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.25rem;
    --space-6: 1.5rem;
    --space-8: 2rem;
    --space-10: 2.5rem;
    --space-12: 3rem;
    --space-16: 4rem;
    --space-20: 5rem;
    --space-40: 10rem;

    /* ---- SECTION RHYTHM (vertical space between sections) ----
       Overridden per breakpoint in the responsive section at the end. */
    --section-y: 10rem;
    --section-y-tight: 6rem;

    /* ---- RADIUS ----
       RAISED, because the previous values were too tight for surfaces that hold text.

       The scale now runs small to large in the order the names suggest. It did not
       before: --radius-lg was 2.5rem and --radius-xl was 2rem, so "lg" was larger
       than "xl" and the two were impossible to reason about. --radius-lg is the
       biggest now and --radius-xl sits under it, which is still odd naming, so treat
       --radius-lg as "the very round one" rather than as a step above xl.

       --radius-sm is for small items that sit inside something else: a checkbox row,
       a dropdown item, a thumbnail. --radius-md is the workhorse and covers every
       panel, card, field and menu that contains text. */
    --radius-sm: 0.75rem;
    --radius-md: 1.25rem;
    --radius-lg: 2.5rem;
    --radius-xl: 2rem;
    --radius-full: 9999px;
}

/* =============================================================================
   2. BASE / RESET
   ============================================================================= */

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

html { scroll-behavior: smooth; }

body {
    font-family: var(--font-body);
    font-size: 1rem;
    line-height: 1.6;
    color: var(--color-on-surface);
    background-color: var(--color-surface);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: hidden;
}

img, picture, svg { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; transition: color 150ms ease; }
button { font: inherit; background: none; border: none; cursor: pointer; }
input, select, textarea { font: inherit; color: inherit; }
ul, ol { list-style: none; }

::selection { background-color: color-mix(in srgb, var(--color-primary) 40%, transparent); color: var(--color-on-surface); }
/* Keyboard focus. A light outline plus a dark green halo, so the indicator
   stays visible on both the white panels and the near-black ones. */
:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
    box-shadow: 0 0 0 4px var(--color-panel-green);
}

/* =============================================================================
   3. TYPOGRAPHY
   ============================================================================= */

h1, h2, h3, h4, h5 {
    font-family: var(--font-headline);
    font-weight: 600;
    line-height: 1.1;
    letter-spacing: -0.02em;
    color: inherit;
}
/* The hero statement is the one place Leafy stays: it is single weight, so it
   must not be synthetically bolded. */
h1,
.display-1 {
    font-family: var(--font-display);
    font-weight: 400;
}

.display-1 {
    font-size: clamp(2.6rem, 6vw, 4.75rem);
    letter-spacing: -0.03em;
}
.display-2 { font-size: clamp(2rem, 4.5vw, 3.4rem); letter-spacing: -0.03em; }
.h2 { font-size: clamp(1.7rem, 3.2vw, 2.5rem); }
.h3 { font-size: 1.4rem; }
.h4 { font-size: 1.15rem; }
.lede { font-size: clamp(1.05rem, 1.6vw, 1.25rem); color: var(--color-on-surface-variant); }
.eyebrow { font-size: .78rem; font-weight: 700; text-transform: uppercase; letter-spacing: .14em; color: var(--color-primary-dark); }

.text-primary { color: var(--color-primary); }
.text-gradient {
    background: linear-gradient(120deg, var(--color-primary), var(--color-primary-light));
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

/* =============================================================================
   4. LAYOUT & UTILITIES
   ============================================================================= */

.container { width: 100%; max-width: 1180px; margin-inline: auto; padding-inline: 1.5rem; }
.container-wide { max-width: 1360px; }
.section { padding: var(--section-y) 0; }
/* Wait-list section: extra space before the footer. The extra padding also
   extends this section's gradient so it eases into the dark footer. */
.join-section { padding-bottom: calc(var(--section-y) + var(--space-12)); }
/* The wait-list card is roomier than a normal card. The padding lives here
   rather than inline on the element because a phone needs it much tighter, and
   an inline style cannot be overridden by the responsive block. */
.join-card { padding: 2.5rem; margin-top: 2.5rem; }
.section-tight { padding: var(--section-y-tight) 0; }
.center { text-align: center; }
.section-head { max-width: 720px; margin-inline: auto; }
.section-head .lede { margin-top: var(--space-4); }

.grid { display: grid; gap: var(--space-6); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }

/* A grid item defaults to min-width:auto, so the widest unbreakable thing inside
   it sets a floor the column is not allowed to shrink below. Whenever that floor
   was wider than a phone, a single column section still overflowed its container
   and .has-decal's overflow:hidden clipped the right hand edge instead of
   scrolling. min-width:0 removes the floor so a track can be the width it was
   asked to be. */
.grid > *,
.hero-grid > *,
.ways-grid > *,
.stats-band > *,
.compare-body > *,
.cat-grid > *,
.footer-grid > *,
.refer-rewards-grid > * { min-width: 0; }

.flex { display: flex; }
.flex-sb { display: flex; align-items: center; justify-content: space-between; }
.flex-center { display: flex; align-items: center; justify-content: center; }
.flex-col { display: flex; flex-direction: column; }
.flex-wrap { flex-wrap: wrap; }
.gap-2 { gap: var(--space-2); }
.gap-4 { gap: var(--space-4); }
.gap-6 { gap: var(--space-6); }
.gap-8 { gap: var(--space-8); }
.mt-4 { margin-top: var(--space-4); }
.mt-6 { margin-top: var(--space-6); }
.mt-8 { margin-top: var(--space-8); }
.mt-12 { margin-top: var(--space-12); }
.mb-4 { margin-bottom: var(--space-4); }
.mb-8 { margin-bottom: var(--space-8); }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); border: 0; }

.divider { height: 1px; background: var(--color-surface-variant); border: none; }

/* =============================================================================
   5. BUTTONS
   ============================================================================= */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-6);
    font-weight: 700;
    font-size: .95rem;
    border-radius: var(--radius-full);
    transition: transform .25s cubic-bezier(.34,1.56,.64,1), box-shadow .2s ease, background .2s ease, color .2s ease;
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}
.btn-primary {
    background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-light) 100%);
    color: #06200e;
    box-shadow: var(--shadow-green-glow);
    border: 1px solid var(--color-border-glow);
}
.btn-primary:hover { transform: scale(1.04); box-shadow: 0 15px 35px -10px rgba(34,197,94,.5); }
.btn-secondary {
    background: linear-gradient(135deg, #ffffff 0%, #f0f4f1 100%);
    color: var(--color-on-surface);
    border: 1px solid #e4e9e5;
    box-shadow: var(--shadow-md);
}
.btn-secondary:hover { color: var(--color-primary-dark); transform: scale(1.04); }
.btn-light {
    background: #fff;
    color: var(--color-primary-darker);
    border: 1px solid transparent;
    box-shadow: 0 10px 24px -14px rgba(0,0,0,.45);
}
.btn-light:hover { transform: scale(1.04); box-shadow: 0 14px 30px -14px rgba(0,0,0,.5); }
.btn-ghost { background: transparent; border: 1px solid rgba(255,255,255,.22); color: #fff; }
.btn-ghost:hover { border-color: var(--color-primary); color: var(--color-primary-light); transform: scale(1.03); }

/* The same idea on a light surface.
   .btn-ghost is white on a white border, which is right on the ink sections it was
   built for and invisible on a form. Rather than change it and break those, this is
   the light-background variant: same shape, colours that can be seen. */
.btn-ghost-dark { background: transparent; border: 1px solid var(--color-outline); color: var(--color-on-surface-variant); }
.btn-ghost-dark:hover { border-color: var(--color-primary); color: var(--color-primary-dark); transform: none; }
/* Full width buttons live in cards and forms, where the label can easily be
   longer than the box. The base .btn is nowrap, which is right in a header or a
   hero row but wrong here: "I'm a business. Count me in" is about 280px of
   unbreakable text, which set a floor the card could not shrink below and
   pushed the whole grid past the width of a phone. Full width buttons wrap. */
.btn-block { width: 100%; white-space: normal; text-align: center; line-height: 1.25; }
.btn-lg { padding: var(--space-4) var(--space-8); font-size: 1.05rem; }
.btn-sm { padding: var(--space-2) var(--space-4); font-size: .85rem; }

/* A button hidden with the `hidden` attribute has to actually disappear. The
   .btn rule above sets display: inline-flex, and an author rule beats the
   browser's own [hidden] rule, so without this the attribute does nothing.
   That is why Back, Continue and Publish all showed at once on the wizard. */
.btn[hidden] { display: none; }

/* =============================================================================
   6. FORMS & INPUTS
   ============================================================================= */

.input-group {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: .35rem .35rem .35rem 1.25rem;
    border: 1px solid color-mix(in srgb, var(--color-primary) 20%, transparent);
    border-radius: var(--radius-full);
    background: var(--color-surface-elevated);
    box-shadow: var(--shadow-md);
}
.input-group:focus-within { border-color: var(--color-primary); box-shadow: 0 0 0 4px var(--color-primary-dim); }
.input-group input {
    flex: 1;
    border: none;
    background: transparent;
    outline: none;
    color: var(--color-on-surface);
    font-size: 1rem;
    padding: var(--space-2) 0;
}
.input-group input::placeholder { color: var(--color-on-surface-inverse); }
.input-group .btn { flex-shrink: 0; }

.field {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    text-align: left;

    /* A flex item's default min-width is auto, which means it refuses to shrink below
       its content. A .choice-row inside a .field is a flex item, so without this the
       row cannot shrink, the chips are stretched to fill it, and a checkbox at the far
       left of a wide chip reads as though it is not there at all.
       This is the same guard the rest of the file carries on every other flex child:
       .partner-set, .hero-row, .join-held-body and .profile-logo-copy all set it. */
    min-width: 0;
}

/* The head of a section: title, then its lede. Gives the lede room to be a separate
   thought rather than a subtitle stuck to the heading. */
.profile-set .profile-set-lede { margin-top: var(--space-3); }
.field label { font-weight: 600; font-size: .9rem; color: var(--color-on-surface-variant); }
.input {
    width: 100%;
    padding: var(--space-3) var(--space-5);
    border: 1px solid #dfe6e0;
    border-radius: var(--radius-full);
    background: #fff;
    color: var(--color-on-surface);
    /* THE SAME NORMALISATION .select ALREADY HAS, and it was missing here.
       Chrome applies `appearance: menulist-button` to an input it has
       AUTOFILLED, which drops the control back to native rendering and
       discards border-radius. The field was a pill until the browser filled
       it in and a sharp rectangle afterwards, on every form on the site.
       Turning appearance off stops the native control showing through. */
    appearance: none;
    -webkit-appearance: none;
    transition: border-color 150ms ease, box-shadow 150ms ease;
}

/* Autofill also repaints the background with the browser's own colour, which
   arrives as a pale blue rectangle inside a white pill. A huge inset shadow
   covers it without touching the real background, which is the only way to
   beat a UA rule that cannot be unset. The colour is ours, so an autofilled
   field looks like every other field. */
.input:-webkit-autofill,
.input:-webkit-autofill:hover,
.input:-webkit-autofill:focus {
    -webkit-text-fill-color: var(--color-on-surface);
    -webkit-box-shadow: 0 0 0 1000px #fff inset;
    box-shadow: 0 0 0 1000px #fff inset;
}

.input::placeholder { color: var(--color-on-surface-inverse); }
.input:focus { outline: none; border-color: var(--color-primary); box-shadow: 0 0 0 4px var(--color-primary-dim); }

/* A MULTI-LINE FIELD IS NOT A PILL.
   .input's radius is --radius-full, which is right for a one line field and wrong
   for anything with height: a 7 row textarea gets stadium ends and reads as a
   rendering fault rather than a form control.
   This is stated once, here, on the ELEMENT rather than on a class, so any textarea
   that carries .input is fixed whether or not whoever wrote it knew to add a
   modifier. It is the third time this has come up: .survey-textarea and .textarea
   each patched it locally before this rule existed. Those two still set their own
   padding, height and resize, which is fine; they no longer need to fix the radius.
   Specificity: .input is (0,1,0) and this is (0,0,1) with an element selector, so
   the two local patches below still win on anything they set. That is deliberate. */
textarea.input {
    border-radius: var(--radius-md);
}

/* Line height and family, so text in a box behaves like text in a box rather than
   like a single line of a form control. */
textarea.input {
    line-height: 1.55;
    font-family: var(--font-body);
    resize: vertical;
}
.select {
    width: 100%;
    padding: var(--space-3) var(--space-5);
    border: 1px solid #dfe6e0;
    border-radius: var(--radius-full);
    background-color: #fff;
    color: var(--color-on-surface);
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23545a56' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 1rem center;
}
.select:focus { outline: none; border-color: var(--color-primary); box-shadow: 0 0 0 4px var(--color-primary-dim); }

/* The opened list. The browser draws this itself and honours only a little, but
   background and colour are widely supported, so it stops looking like a
   different product from the box it dropped out of. */
.select option,
.select optgroup {
    background: #fff;
    color: var(--color-on-surface);
    font-family: var(--font-body);
}
.select optgroup { font-weight: 700; }
.required { color: var(--color-error); }
.form-status { min-height: 1.5rem; font-weight: 600; margin-top: var(--space-4); }
.form-status.ok { color: var(--color-primary-dark); }
.form-status.err { color: var(--color-error); }
/* In progress. Neither a success nor a failure, so it must not borrow either
   colour: showing "Sending..." in red made every submission look like it had
   already failed. */
.form-status.pending { color: var(--color-on-surface-muted); }

/* =============================================================================
   7. CARDS / GLASS / BADGES / DIVIDERS
   ============================================================================= */

.card {
    background: var(--color-surface-elevated);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    padding: var(--space-6);
    border: 1px solid #eef1ee;
}
.card-glass {
    background: rgba(255, 255, 255, 0.72);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border: 1px solid var(--color-border-glow);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-lg);
}
.card-glass-onblack {
    background: rgba(255, 255, 255, 0.05);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border: 1px solid rgba(255, 255, 255, 0.13);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-lg);
}
.card-hover { transition: transform .25s cubic-bezier(.34,1.56,.64,1), box-shadow .25s ease; }
.card-hover:hover { transform: translateY(-6px); box-shadow: 0 24px 48px -20px rgba(34,197,94,.35); }

.badge {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: var(--space-1) var(--space-3);
    background: var(--color-primary-dim);
    color: var(--color-primary-dark);
    border-radius: var(--radius-full);
    font-size: .7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
}
.inline-badge { width: fit-content; }
.badge-icon {
    width: 44px; height: 44px;
    flex: 0 0 44px;
    border-radius: var(--radius-md);
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--color-primary-dim);
    color: var(--color-primary-dark);
    font-size: 1.4rem;
}
.badge-on-dark { background: rgba(34,197,94,.16); color: var(--color-primary-light); }
.badge-icon-onblack {
    width: 44px; height: 44px;
    flex: 0 0 44px;
    border-radius: var(--radius-md);
    display: inline-flex; align-items: center; justify-content: center;
    background: rgba(34,197,94,.16);
    color: var(--color-primary-light);
    font-size: 1.4rem;
}

/* =============================================================================
   8. EFFECTS - blur-decals & glows (Enterramon signature)
   ============================================================================= */

.has-decal { position: relative; overflow: hidden; }

.blur-decal {
    position: absolute;
    border-radius: 50%;
    filter: blur(80px);
    pointer-events: none;
    z-index: 0;
}

/* ---- Brand decals: the supplied leaf artwork, placed as decoration ----
   Sized and positioned per instance inline. Always sits behind content (the
   content wrappers carry .z-10), never intercepts clicks, and is clipped by
   the .has-decal section it lives in. */
.decal {
    position: absolute;
    z-index: 0;
    height: auto;
    pointer-events: none;
    user-select: none;
    opacity: .07;
    /* Parallax offset is written here by JS. Uses `translate` rather than
       `transform` so it never clobbers the drift keyframes. */
    translate: 0 var(--decal-shift, 0px);
}
/* Deliberate size tiers, so the artwork reads as a system rather than a set of
   one-off placements. Position is set per instance; size is not. */
.decal-sm { width: 240px; }
.decal-md { width: 330px; }
.decal-lg { width: 470px; }
/* Green on a dark section needs a touch more presence than green on white. */
.decal-on-dark { opacity: .11; }
/* A GLYPH DECAL SIZES BY FONT, NOT BY WIDTH, so the tiers above cannot express
   it: `.decal-lg` sets a 470px BOX, and a 1rem glyph would sit tiny inside it.
   The crown watermark on the Business Pro site card is a Material Symbols glyph,
   so its size is stated here as a font-size at the same 240px the `.decal-sm`
   artwork tier uses. Everything else about it - absolute position, z-index 0,
   the faded opacity, `pointer-events: none`, and clipping by `.has-decal` -
   comes from `.decal` unchanged, so it behaves like every other decal. */
.decal-crown { font-size: 15rem; line-height: 1; }
.blur-decal-md { width: 380px; height: 380px; }
.blur-decal-ms { width: 240px; height: 240px; }
.blur-decal-green { background: radial-gradient(circle, rgba(34,197,94,.5), transparent 70%); opacity: .5; }
.blur-decal-lime { background: radial-gradient(circle, rgba(134,239,172,.55), transparent 70%); opacity: .5; }

.relative { position: relative; }
.z-10 { position: relative; z-index: 10; }

/* =============================================================================
   9. HEADER / NAV
   ============================================================================= */

.site-header {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 100;
    transition: background .25s ease, box-shadow .25s ease, backdrop-filter .25s ease;
}
.site-header.scrolled {
    background: rgba(11, 15, 12, .72);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-bottom: 1px solid rgba(255,255,255,.08);
}
.header-inner { display: flex; align-items: center; justify-content: space-between; height: 72px; }
.brand { display: inline-flex; align-items: center; gap: .6rem; font-family: var(--font-headline); font-weight: 600; font-size: 1.25rem; color: #fff; }
.brand-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    flex: 0 0 36px;
    line-height: 1;
    user-select: none;
}
/* The mark is the supplied leaf logo art (transparent WebP), so no badge
   background is painted behind it. */
.brand-mark img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
}
/* Every icon box nests its glyph in a child span. That child is a flex item, so
   it is centred by the box rather than by font metrics. */
.way-icon .material-symbols-outlined,
.pain-icon .material-symbols-outlined,
.badge-icon .material-symbols-outlined,
.badge-icon-onblack .material-symbols-outlined { display: block; line-height: 1; }

/* Defensive guard. If an icon-box class ever ends up on the SAME element as the
   icon-font class again, the icon-font rule's display:inline-block would win and
   pin the glyph to the top-left. These rules keep it centred regardless. */
.badge-icon.material-symbols-outlined,
.badge-icon-onblack.material-symbols-outlined,
.pain-icon.material-symbols-outlined,
.way-icon.material-symbols-outlined,
.win-num.material-symbols-outlined,
.join-held-icon.material-symbols-outlined {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    text-align: center;
}

.brand-name { letter-spacing: -0.01em; white-space: nowrap; }
.brand-tld { color: var(--color-primary); }
.nav-links { display: flex; align-items: center; gap: var(--space-6); }
.nav-links a { color: rgba(255,255,255,.75); font-weight: 600; font-size: .92rem; }
.nav-links a:hover { color: #fff; }
.nav-cta { display: flex; align-items: center; gap: var(--space-3); }

/* The links and the CTA are grouped in one element so the burger can open a
   single panel on a phone. On desktop this is just a row on the right. */
.nav-menu { display: flex; align-items: center; gap: var(--space-6); }

/* Phones only. The open state lives in the 720px block further down. */
.nav-burger { display: none; }

/* The bar behind the header is transparent until the page is scrolled. While the
   panel is open it needs a solid bar, or the panel looks detached from the logo. */
.site-header.menu-open {
    background: rgba(11, 15, 12, .97);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-bottom: 1px solid rgba(255,255,255,.08);
}

/* =============================================================================
   10. HERO
   ============================================================================= */

.hero {
    position: relative;
    overflow: hidden;
    background:
        radial-gradient(1100px 620px at 82% -10%, rgba(34,197,94,.25), transparent 60%),
        radial-gradient(900px 500px at -10% 20%, rgba(134,239,172,.14), transparent 55%),
        var(--color-ink);
    color: #fff;
    padding: var(--space-40) 0 var(--space-20);
    min-height: 92vh;
    display: flex;
    align-items: center;
}
.hero .container { position: relative; z-index: 2; }
.hero-grid { display: grid; grid-template-columns: 1.1fr .9fr; gap: var(--space-12); align-items: center; }
.hero h1 { color: #fff; }
.hero .lede { color: rgba(255,255,255,.72); margin-top: var(--space-6); max-width: 560px; }
.hero-cta { display: flex; gap: var(--space-3); flex-wrap: wrap; margin-top: var(--space-8); }
.hero-panel { position: relative; }
.hero-panel-card { padding: var(--space-8); }
/* Hero stat list. The row must NOT use the .center utility (that sets
   text-align:center and left one row aligned differently from the others). */
.hero-stats { display: flex; flex-direction: column; gap: var(--space-4); margin-top: var(--space-6); }
.hero-stat-row { display: flex; align-items: center; gap: var(--space-4); text-align: left; }
.hero-stat { min-width: 0; }
.hero-stat b { display: block; color: #fff; font-size: 1.1rem; line-height: 1.25; }
.hero-stat p { margin: 0; color: rgba(255,255,255,.55); font-size: .85rem; line-height: 1.35; }

/* =============================================================================
   11. SECTIONS
   ============================================================================= */

/* Trust / stats band */
.stats-band { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-6); }
.stat { text-align: center; padding: var(--space-6); }
.stat b { display: block; font-family: var(--font-headline); font-weight: 600; font-size: clamp(2rem, 4vw, 3rem); letter-spacing: -.03em; color: var(--color-primary-dark); }
.stat span { font-size: .9rem; color: var(--color-on-surface-variant); }

/* Feature cards */
.feature-card { display: flex; flex-direction: column; gap: var(--space-4); height: 100%; }
.feature-card h3 { font-size: 1.15rem; }
.feature-card p { color: var(--color-on-surface-variant); font-size: .95rem; }

/* Track cards */
.track-card { display: flex; flex-direction: column; gap: var(--space-4); height: 100%; }
.track-card .btn { margin-top: var(--space-6); }

/* Row-for-row alignment across the three track cards.
   Each card spans the parent's rows and re-uses them via subgrid, and the
   bullet list does the same, so badges, titles, descriptions, every bullet,
   the tags and the buttons all sit on the same lines across all three columns.
   Scoped to multi-column widths, so the single-column phone layout keeps the
   original flex column. Browsers without subgrid fall back to it as well. */
@media (min-width: 721px) {
    @supports (grid-template-rows: subgrid) {
        .tracks-grid {
            grid-template-rows: auto auto auto repeat(4, auto) auto auto;
            row-gap: var(--space-4);
        }
        .track-card {
            display: grid;
            grid-row: span 9;
            grid-template-rows: subgrid;
            row-gap: var(--space-4);
            height: auto;
        }
        .track-card .track-list {
            display: grid;
            grid-row: span 4;
            grid-template-rows: subgrid;
            gap: var(--space-3);
            margin-top: 0;
        }
        .track-card .tag-row { margin-top: 0; }
        .track-card .btn { margin-top: 0; }
    }
}
.track-list { display: flex; flex-direction: column; gap: var(--space-3); margin-top: var(--space-2); }
/* These bullets only ever sit on the dark track cards, so the text must be
   light. The on-surface-variant token is built for light backgrounds and was
   measuring 2.55:1 here. */
.track-list li { display: flex; align-items: flex-start; gap: .6rem; font-size: .95rem; color: rgba(255,255,255,.82); }
.track-list li .material-symbols-outlined { color: var(--color-primary); font-size: 1.2rem; margin-top: 2px; }
.tag-row { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: auto; }
.tag { font-size: .75rem; font-weight: 700; padding: .3rem .8rem; border-radius: var(--radius-full); background: var(--color-primary-dim); color: var(--color-primary-dark); }

/* How it works */
.step { position: relative; padding: var(--space-6); }
.step-num {
    width: 48px; height: 48px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    background: linear-gradient(135deg, var(--color-primary), var(--color-primary-light));
    color: #06200e; font-family: var(--font-headline); font-weight: 600; font-size: 1.2rem;
    margin-bottom: var(--space-4);
}
.step h3 { font-size: 1.15rem; }
.step p { color: var(--color-on-surface-variant); font-size: .95rem; margin-top: .5rem; }

/* Pricing glimpse */
.price-card { text-align: center; padding: var(--space-8); display: flex; flex-direction: column; gap: var(--space-4); height: 100%; }
.price-card .amount { font-family: var(--font-headline); font-weight: 600; font-size: clamp(2.2rem, 4vw, 3rem); letter-spacing: -.03em; }
.price-card .per { font-size: .85rem; color: var(--color-on-surface-variant); }
.price-card ul { text-align: left; display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-2); }
.price-card ul li { display: flex; align-items: flex-start; gap: .6rem; font-size: .92rem; color: var(--color-on-surface-variant); }
.price-card ul li .material-symbols-outlined { color: var(--color-primary); font-size: 1.15rem; }
.price-card.featured { background: var(--color-ink); color: #fff; }
.price-card.featured .per, .price-card.featured ul li { color: rgba(255,255,255,.65); }
.price-card.featured .amount { color: var(--color-primary-light); }

/* FAQ accordion */
.faq-item { border-bottom: 1px solid var(--color-surface-variant); }
.faq-q {
    width: 100%;
    display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
    padding: var(--space-5) 0;
    text-align: left;
    font-family: var(--font-headline); font-weight: 600; font-size: 1.05rem; color: var(--color-on-surface);
}
.faq-q .material-symbols-outlined { transition: transform .25s ease; color: var(--color-primary-dark); }
.faq-item.open .faq-q .material-symbols-outlined { transform: rotate(180deg); }
/* max-height alone only hides the answer visually; a screen reader still reads
   it. visibility takes it out of the accessibility tree, and the delayed
   transition keeps the collapse animation intact. */
.faq-a {
    max-height: 0;
    overflow: hidden;
    visibility: hidden;
    transition: max-height .3s ease, visibility 0s linear .3s;
}
.faq-item.open .faq-a {
    max-height: 400px;
    visibility: visible;
    transition: max-height .3s ease, visibility 0s;
}
.faq-a p { padding-bottom: var(--space-5); color: var(--color-on-surface-variant); }

/* ---- Pain cards (the "real cost" of doing it yourself) ---- */
.pain-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-6); }
.pain-card {
    display: flex;
    gap: var(--space-5);
    padding: var(--space-6);
    border-radius: var(--radius-lg);
    background: var(--color-surface-elevated);
    border: 1px solid #eef1ee;
    box-shadow: var(--shadow-md);
}
.pain-icon {
    flex: 0 0 48px;
    width: 48px; height: 48px;
    border-radius: var(--radius-md);
    display: inline-flex; align-items: center; justify-content: center;
    background: rgba(176, 37, 0, .1);
    color: var(--color-error);
    font-size: 1.5rem;
}
.pain-card h3 { font-size: 1.15rem; }
.pain-card p { margin-top: .5rem; color: var(--color-on-surface-variant); font-size: .95rem; }

/* ---- Dark callout panel ---- */
.callout {
    position: relative;
    overflow: hidden;
    margin-top: var(--space-10);
    padding: var(--space-12) var(--space-8);
    border-radius: var(--radius-xl);
    background: var(--color-ink);
    text-align: center;
    color: #fff;
}
.callout h3 { font-size: clamp(1.4rem, 3vw, 2.1rem); color: #fff; }
.callout p { max-width: 620px; margin: var(--space-4) auto 0; color: rgba(255,255,255,.65); }
.callout .btn { margin-top: var(--space-6); }

/* ---- onTheMove wordmark ---- */
.otm-name { font-family: var(--font-headline); color: inherit; white-space: nowrap; }
.otm-name span { color: var(--color-primary); }

/* ---- Comparison: the big marketplaces vs onTheMove ---- */
.compare-plan {
    margin-top: var(--space-10);
    text-align: center;
    font-size: .8rem;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--color-primary-light);
}
.compare {
    margin-top: var(--space-5);
    border-radius: var(--radius-xl);
    overflow: hidden;
    border: 1px solid rgba(255,255,255,.12);
    background: rgba(255,255,255,.02);
}
.compare-head { display: grid; grid-template-columns: 1fr 1fr; }
.compare-head > div {
    padding: var(--space-4) var(--space-6);
    font-family: var(--font-headline);
    font-size: 1rem;
    display: flex; align-items: center; gap: .5rem;
}
.compare-head .old { background: rgba(255,255,255,.04); color: rgba(255,255,255,.55); }
.compare-head .new { background: rgba(34,197,94,.16); color: var(--color-primary-light); }
/* The two sides hold different numbers of points (7 vs 6), so they are
   independent columns rather than paired rows. Both columns stretch to the same
   height and the shorter one's last row absorbs the slack, so the tinted panel
   always reaches the bottom edge instead of stopping short. */
.compare-body { display: grid; grid-template-columns: 1fr 1fr; }
.compare-col { display: flex; flex-direction: column; }
.compare-col--new { background: rgba(34,197,94,.05); }
.compare-col .compare-item:last-child { flex: 1 1 auto; }
.compare-item {
    padding: var(--space-5) var(--space-6);
    display: flex; gap: var(--space-3); align-items: flex-start;
    border-top: 1px solid rgba(255,255,255,.08);
    font-size: .95rem; line-height: 1.45;
    color: rgba(255,255,255,.5);
}
.compare-item .material-symbols-outlined {
    font-size: 1.15rem; flex: 0 0 auto; margin-top: 1px;
    color: rgba(255,255,255,.32);
}
.compare-col--new .compare-item { color: #fff; }
.compare-col--new .compare-item .material-symbols-outlined { color: var(--color-primary); }
/* Shown only on phones, where the header row is hidden and each stacked list
   needs its own label. */
.compare-mobile-label { display: none; }
.compare-note { margin-top: var(--space-6); text-align: center; color: rgba(255,255,255,.6); font-size: .95rem; }

/* ---- Three-up track picker (signup form) ---- */
.track-picker { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-3); }

/* ---- Affiliate "what you actually need" panel ---- */
.need-panel {
    border-radius: var(--radius-xl);
    padding: var(--space-8);
    background: var(--color-ink);
    color: #fff;
}
.need-panel h3 { color: #fff; font-size: 1.35rem; }
.need-panel > p { color: rgba(255,255,255,.65); margin-top: var(--space-3); }
.need-list { display: flex; flex-direction: column; gap: var(--space-3); margin-top: var(--space-6); }
.need-list li { display: flex; align-items: flex-start; gap: .6rem; color: rgba(255,255,255,.85); font-size: .95rem; }
.need-list li .material-symbols-outlined { color: var(--color-primary); font-size: 1.2rem; margin-top: 1px; }

/* ---- Operation picker (sits inside the white stats band) ---- */
.audience-pick {
    margin-top: var(--space-12);
    padding-top: var(--space-12);
    border-top: 1px solid var(--color-surface-variant);
    text-align: center;
}
.audience-q { font-family: var(--font-headline); font-size: clamp(1.2rem, 2.4vw, 1.6rem); color: var(--color-on-surface); }
.audience-switch { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-3); margin-top: var(--space-6); }
.audience-btn {
    display: inline-flex; align-items: center; gap: var(--space-2);
    padding: var(--space-4) var(--space-8);
    border-radius: var(--radius-full);
    border: 1px solid #dfe6e0;
    background: #fff;
    color: var(--color-on-surface);
    font-weight: 700;
    font-size: 1rem;
    cursor: pointer;
    box-shadow: var(--shadow-sm);
    transition: transform .2s ease, background .2s ease, color .2s ease,
                border-color .2s ease, box-shadow .2s ease;
}
.audience-btn:hover { border-color: var(--color-primary); color: var(--color-primary-dark); transform: translateY(-2px); }
.audience-btn.is-active {
    background: linear-gradient(135deg, var(--color-primary), var(--color-primary-light));
    color: #06200e;
    border-color: transparent;
    box-shadow: var(--shadow-green-glow);
}
.audience-btn .material-symbols-outlined { font-size: 1.25rem; }
.audience-hint { margin-top: var(--space-5); font-size: .9rem; color: var(--color-on-surface-inverse); }

/* ---- Affiliate: how they win ---- */
.win-panel {
    margin-top: var(--space-10);
    padding: var(--space-8);
    border-radius: var(--radius-xl);
    background: var(--color-secondary);
}
.win-panel h3 { font-size: 1.35rem; color: var(--color-on-secondary); }
.win-panel > p { margin-top: var(--space-3); color: var(--color-on-secondary); opacity: .85; }
.win-grid { margin-top: var(--space-8); gap: var(--space-6); }
.win { display: flex; flex-direction: column; gap: var(--space-3); }
.win-num {
    width: 36px; height: 36px;
    flex: 0 0 36px;
    border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    text-align: center;
    background: var(--color-primary);
    color: #06200e;
    font-size: 1.1rem;
}
/* The icon glyph is nested in its own span rather than sharing this element,
   so the sizing class and the icon-font class can never fight over display. */
.win-num .material-symbols-outlined { display: block; line-height: 1; }
.win h4 { font-size: 1rem; color: var(--color-on-secondary); }
.win p { font-size: .9rem; color: var(--color-on-secondary); opacity: .85; }

/* Only the selected audience's section is shown. */
[data-audience][hidden] { display: none !important; }

/* ---- Four ways to get involved ---- */
.ways-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-6); }
.way {
    /* A grid item defaults to min-width:auto, which means the widest thing
       inside it sets a floor the track is not allowed to shrink below. Here
       that widest thing was the one line CTA button, so the track refused to
       take its 1fr share, the grid grew past .container, and .has-decal's
       overflow:hidden clipped the cards on the right. min-width:0 removes the
       floor so the track can be the width it was supposed to be. */
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    height: 100%;
    padding: var(--space-6);
    border-radius: var(--radius-lg);
    background: var(--color-surface-elevated);
    border: 1px solid #eef1ee;
    box-shadow: var(--shadow-md);
    transition: transform .3s cubic-bezier(.34,1.56,.64,1), box-shadow .3s ease, border-color .3s ease;
}
.way:hover {
    transform: translateY(-5px);
    border-color: color-mix(in srgb, var(--color-primary) 35%, transparent);
    box-shadow: 0 22px 42px -22px rgba(34,197,94,.45);
}
.way-icon {
    width: 46px; height: 46px;
    flex: 0 0 46px;
    border-radius: var(--radius-md);
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--color-primary-dim);
    color: var(--color-primary-dark);
    font-size: 1.4rem;
}
.way h3 { font-size: 1.1rem; }
.way p { font-size: .93rem; color: var(--color-on-surface-variant); }

/* ---- Referral block (front end only; rewards are wired up later) ---- */
.refer-panel {
    margin-top: var(--space-8);
    padding: var(--space-8);
    border-radius: var(--radius-xl);
    background: var(--color-panel-green);
    color: #fff;
}
.refer-head { display: flex; align-items: center; gap: var(--space-3); }
.refer-icon {
    width: 40px; height: 40px;
    flex: 0 0 40px;
    border-radius: var(--radius-md);
    display: inline-flex; align-items: center; justify-content: center;
    background: #fff;
    color: var(--color-panel-green);
    font-size: 1.25rem;
}
.refer-panel h3 { font-size: 1.35rem; color: #fff; }
.refer-panel > p { margin-top: var(--space-3); color: rgba(255,255,255,.9); }
.refer-label {
    display: block;
    margin-top: var(--space-6);
    margin-bottom: var(--space-2);
    font-size: .9rem;
    font-weight: 600;
    color: rgba(255,255,255,.9);
}
/* The default ghost hover turns green, which would vanish on a green panel. */
.refer-panel .btn-ghost { border-color: rgba(255,255,255,.55); }
.refer-panel .btn-ghost:hover {
    border-color: #fff;
    background: rgba(255,255,255,.14);
    color: #fff;
}
.refer-row { display: flex; gap: var(--space-3); flex-wrap: wrap; }
.refer-row .btn { flex: 0 0 auto; }
.refer-input {
    flex: 1 1 240px;
    min-width: 0;
    padding: var(--space-3) var(--space-5);
    border-radius: var(--radius-full);
    border: 1px solid transparent;
    background: #fff;
    color: var(--color-on-surface);
    font-size: .95rem;
}
.refer-input:focus { outline: none; box-shadow: 0 0 0 4px rgba(255,255,255,.45); }
/* What the points buy. Sits on the green panel, so everything is light-on-green. */
.refer-rewards { margin-top: var(--space-8); }
/* Sentence case and lighter weight: the panel already carries a title, a lede
   and two field labels, so another shouty heading just added noise. */
.refer-rewards h4 {
    font-size: .85rem;
    font-weight: 600;
    color: rgba(255,255,255,.65);
}
.refer-rewards-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-3) var(--space-5);
    margin-top: var(--space-4);
}
.refer-reward {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    font-size: .92rem;
    line-height: 1.4;
    color: rgba(255,255,255,.94);
}
.refer-reward .material-symbols-outlined {
    font-size: 1.05rem;
    flex: 0 0 auto;
    margin-top: 1px;
    color: rgba(255,255,255,.5);
}
.refer-note { margin-top: var(--space-5); font-size: .82rem; color: rgba(255,255,255,.78); }

/* ---- Our story ---- */
.story-body {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
    margin-top: var(--space-6);
}
.story-body p {
    font-size: clamp(1.02rem, 1.5vw, 1.15rem);
    line-height: 1.7;
    color: rgba(255,255,255,.76);
}
.story-pull {
    margin: var(--space-8) 0;
    padding-left: var(--space-6);
    border-left: 3px solid var(--color-primary);
    font-family: var(--font-headline);
    font-size: clamp(1.3rem, 2.6vw, 1.85rem);
    line-height: 1.25;
    color: #fff;
}
.story-closer {
    margin-top: var(--space-8);
    font-family: var(--font-headline);
    font-size: clamp(1.1rem, 1.9vw, 1.35rem);
    line-height: 1.4;
    color: var(--color-primary-light);
}

/* ---- Refinement survey ---- */
/* ONE RULE. This was declared twice: here with margin-top var(--space-4) and
   --color-on-surface-inverse, and again further down with var(--space-3) and
   --color-on-surface-muted. The second silently won both properties, so the first
   was dead code that read as intent. The live values are the ones kept. */
.survey-note {
    margin-top: var(--space-3);
    text-align: center;
    font-size: .85rem;
    color: var(--color-on-surface-muted);
}

/* ---- Sticky mobile CTA ----
   Phones put the wait-list form a long way down, so this rides along once the
   visitor is past the hero and gets out of the way when the form itself is on
   screen. Desktop never sees it. */
.sticky-cta {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 80;
    padding: var(--space-3) var(--space-4) calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
    background: rgba(11, 15, 12, .92);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-top: 1px solid rgba(255, 255, 255, .1);
    transform: translateY(110%);
    transition: transform .3s cubic-bezier(.22, 1, .36, 1);
}
.sticky-cta.is-visible { transform: translateY(0); }

@media (min-width: 721px) {
    .sticky-cta { display: none; }
}

/* ---- Category list (who onTheMove is for) ---- */
.cat-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-10) var(--space-12);
    margin-top: 3rem;
}
.cat-group h3 {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    font-size: 1.02rem;
    color: var(--color-on-surface);
}
.cat-group h3 .material-symbols-outlined {
    width: 36px; height: 36px;
    flex: 0 0 36px;
    border-radius: var(--radius-md);
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--color-primary-dim);
    color: var(--color-primary-dark);
    font-size: 1.15rem;
}
.cat-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-4); }
.cat-chip {
    padding: .4rem .95rem;
    border-radius: var(--radius-full);
    background: var(--color-surface-elevated);
    border: 1px solid #e4e9e5;
    font-size: .88rem;
    color: var(--color-on-surface-variant);
    transition: border-color .2s ease, color .2s ease, transform .2s ease;
}
.cat-chip:hover {
    border-color: var(--color-primary);
    color: var(--color-primary-dark);
    transform: translateY(-1px);
}
/* Chips needing statutory registration get a subtle outline so they read as a
   different kind of category without shouting. */
.cat-chip--reg { border-color: color-mix(in srgb, var(--color-primary) 35%, transparent); }
.cat-reg { margin-left: 1px; font-weight: 700; color: var(--color-primary-dark); }
.cat-reg-note {
    margin-top: var(--space-8);
    text-align: center;
    font-size: .85rem;
    color: var(--color-on-surface-inverse);
}
.cat-missing {
    margin: var(--space-6) 0 var(--space-6);
    text-align: center;
    color: var(--color-on-surface-variant);
}

/* =============================================================================
   12. FOOTER
   ============================================================================= */

.site-footer { background: var(--color-ink); color: rgba(255,255,255,.55); padding: var(--space-16) 0 var(--space-8); }
.footer-grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: var(--space-8); }
.site-footer h2, .site-footer h5 { color: #fff; font-size: .85rem; text-transform: uppercase; letter-spacing: .1em; margin-bottom: var(--space-4); }
.site-footer a { font-size: .9rem; display: block; margin-bottom: var(--space-2); }
.site-footer a:hover { color: var(--color-primary-light); }
/* Pre-launch disclaimer. Deliberately quiet: present and readable, but not
   competing with anything else in the footer. */
.footer-disclaimer {
    max-width: 820px;
    margin-top: var(--space-12);
    padding-top: var(--space-6);
    border-top: 1px solid rgba(255,255,255,.08);
    font-size: .82rem;
    line-height: 1.65;
    color: rgba(255,255,255,.45);
}
.footer-disclaimer strong { color: rgba(255,255,255,.7); }
.footer-bottom { margin-top: var(--space-8); padding-top: var(--space-6); border-top: 1px solid rgba(255,255,255,.08); display: flex; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap; font-size: .85rem; }

/* =============================================================================
   13. ANIMATIONS
   ============================================================================= */

@keyframes fadeUp {
    from { opacity: 0; transform: translateY(18px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes heroIn {
    from { opacity: 0; transform: translateY(28px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes drift {
    0%, 100% { transform: translateY(0) rotate(0deg); }
    50%      { transform: translateY(-14px) rotate(1.5deg); }
}

/* ---- Hero entrance (pure CSS, so it runs with or without JS) ---- */
@media (prefers-reduced-motion: no-preference) {
    .hero .badge,
    .hero h1,
    .hero .lede,
    .hero-cta,
    .hero-panel {
        opacity: 0;
        animation: heroIn .9s cubic-bezier(.22, 1, .36, 1) forwards;
    }
    .hero .badge      { animation-delay: .05s; }
    .hero h1          { animation-delay: .15s; }
    .hero .lede       { animation-delay: .28s; }
    .hero-cta         { animation-delay: .38s; }
    .hero-panel       { animation-delay: .30s; }

    /* Decals breathe gently so the page never feels static. Only the larger
       tiers float, which keeps the number of endless animations down. */
    .decal { animation: drift 14s ease-in-out infinite; }
    .decal-sm { animation: none; }
}

/* ---- Scroll reveal ----
   The hidden state only applies once JS has confirmed it is running (it puts
   .js-reveal on <html> from an inline head script), so with JS disabled every
   section stays fully visible. */
.js-reveal [data-reveal] {
    opacity: 0;
    transform: translateY(26px);
    transition: opacity .8s cubic-bezier(.22, 1, .36, 1),
                transform .8s cubic-bezier(.22, 1, .36, 1);
}
.js-reveal [data-reveal].is-visible {
    opacity: 1;
    transform: none;
}

@media (prefers-reduced-motion: reduce) {
    .js-reveal [data-reveal] { opacity: 1; transform: none; transition: none; }
    .reveal { opacity: 1; }
    html { scroll-behavior: auto; }

    /* Honour the OS setting everywhere, including hover transitions and the
       stat counters, rather than only on the scroll reveals. */
    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
    }
}

/* ---- Richer hover states ---- */
.pain-card { transition: transform .3s cubic-bezier(.34,1.56,.64,1), box-shadow .3s ease, border-color .3s ease; }
.pain-card:hover {
    transform: translateY(-4px);
    border-color: color-mix(in srgb, var(--color-error) 30%, transparent);
    box-shadow: 0 18px 34px -18px rgba(176, 37, 80, .35);
}
.feature-card .badge-icon,
.track-card .track-icon { transition: transform .35s cubic-bezier(.34,1.56,.64,1); }
.feature-card:hover .badge-icon,
.track-card:hover .track-icon { transform: translateY(-3px) scale(1.08); }
.win { transition: transform .3s ease; }
.win:hover { transform: translateY(-3px); }
.step-num { transition: transform .35s cubic-bezier(.34,1.56,.64,1); }
.step:hover .step-num { transform: scale(1.1); }

/* =============================================================================
   14. RESPONSIVE
   ============================================================================= */

/* Four columns need roughly 1170px before the CTA label and the card padding
   fit side by side. Between 1179px and the old 1024px breakpoint the fourth
   column was being clipped on smaller laptops and landscape tablets, so the
   drop to two columns happens earlier now. */
@media (max-width: 1179px) {
    .ways-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 1024px) {
    :root { --section-y: 8rem; --section-y-tight: 5rem; }
    .ways-grid { grid-template-columns: 1fr 1fr; }
    .hero-grid { grid-template-columns: 1fr; }
    .stats-band { grid-template-columns: repeat(2, 1fr); }
    .grid-4 { grid-template-columns: repeat(2, 1fr); }
    .footer-grid { grid-template-columns: 1fr 1fr; }
    /* Six nav links now - tighten so they don't collide with the CTA. */
    .nav-links { gap: var(--space-4); }
    .nav-links a { font-size: .85rem; }
}
@media (max-width: 720px) {
    :root { --section-y: 4.75rem; --section-y-tight: 3.5rem; }
    .grid-3, .grid-2, .grid-4 { grid-template-columns: 1fr; }
    .stats-band { grid-template-columns: 1fr 1fr; }
    /* Header on a phone: the logo and the burger, nothing else. The six links
       and the wait-list button move into the panel the burger opens, which is
       what let the header stop overflowing at 320px wide. */
    /* Just the glyph. No border, no fill, nothing around it. The button is
       still 44px square so the tap target stays comfortable, but the box is
       invisible: the icon alone reads as the control. */
    .nav-burger {
        display: inline-flex; align-items: center; justify-content: center;
        width: 44px; height: 44px;
        padding: 0;
        border: 0;
        border-radius: 0;
        background: none;
        color: #fff;
        cursor: pointer;
    }
    /* Shut: the burger, no cross. Open: the cross, no burger.
       Both state rules carry the attribute selector, so each has three classes
       and each beats the icon rule's two. That was the bug the first time round:
       the rule hiding the cross was a single class and lost to the icon rule, so
       the burger and the cross showed side by side. */
    .nav-burger .material-symbols-outlined { display: none; line-height: 1; font-size: 1.75rem; }
    .nav-burger[aria-expanded="false"] .nav-burger-open { display: block; }
    .nav-burger[aria-expanded="true"]  .nav-burger-shut { display: block; }

    .nav-menu {
        position: absolute;
        top: 72px; left: 0; right: 0;
        display: none;
        flex-direction: column;
        align-items: stretch;
        gap: 0;
        max-height: calc(100vh - 72px);
        overflow-y: auto;
        padding: var(--space-3) var(--space-5) var(--space-6);
        background: rgba(11, 15, 12, .97);
        backdrop-filter: blur(16px);
        -webkit-backdrop-filter: blur(16px);
        border-bottom: 1px solid rgba(255,255,255,.1);
        box-shadow: 0 30px 60px -30px rgba(0,0,0,.85);
    }
    .nav-menu.is-open { display: flex; }

    .nav-links { flex-direction: column; align-items: stretch; gap: 0; }
    .nav-links a {
        padding: var(--space-4) 0;
        font-size: 1rem;
        border-bottom: 1px solid rgba(255,255,255,.08);
    }
    .nav-cta { margin-top: var(--space-5); }
    .nav-cta .btn { width: 100%; }
    /* The header is fixed and overlays this, so this padding is the only lever
       that moves the hero content down. At 5rem the badge started 8px under the
       72px bar, which read as cramped. 11rem gives about 104px of clear air,
       which matches the breathing room the desktop layout gets. */
    .hero { padding: 11rem 0 var(--space-16); min-height: auto; }
    /* Stacked and full width. Two 260px buttons cannot sit side by side on a
       phone, and the base .btn is nowrap so they will not shrink to fit either:
       they would simply run off the right hand edge. */
    .hero-cta { flex-direction: column; align-items: stretch; gap: var(--space-3); margin-top: var(--space-6); }
    .hero-cta .btn { width: 100%; }
    .footer-grid { grid-template-columns: 1fr; }

    /* Hero stat rows: tighten up so the label doesn't wrap awkwardly on phones. */
    .hero-panel-card { padding: var(--space-6); }
    .hero-stat-row { gap: var(--space-3); }
    .badge-icon, .badge-icon-onblack {
        width: 38px; height: 38px; flex: 0 0 38px;
        border-radius: var(--radius-md); font-size: 1.15rem;
    }
    .hero-stat b { font-size: 1rem; }
    .hero-stat p { font-size: .8rem; }

    /* Keep the decorative leaf art from dominating small screens. */
    .decal { max-width: 55vw; }

    /* Less pre-footer padding on phones than the desktop calc gives, and less
       at the top too. With the full 76px above and below, plus a 40px card
       inset and three centred buttons, a 360px screen ended up with about
       232px of usable form and a lot of dead space around it. */
    .join-section { padding-top: 2.75rem; padding-bottom: 3.25rem; }

    /* The wait-list card is the one place a form sits directly in a card, so it
       gets its own tighter inset on a phone. */
    .join-card { padding: 1.25rem; margin-top: 1.75rem; }

    /* Full width and stacked. Centred pills left most of the row empty and were
       a smaller tap target than they needed to be. */
    .track-picker { flex-direction: column; align-items: stretch; }
    .track-picker .btn { width: 100%; }

    /* New content sections on phones */
    .pain-grid { grid-template-columns: 1fr; }
    .pain-card { gap: var(--space-4); padding: var(--space-5); }
    .pain-icon { flex: 0 0 40px; width: 40px; height: 40px; font-size: 1.25rem; }
    .callout { padding: var(--space-8) var(--space-5); }
    .need-panel { padding: var(--space-6); }

    /* Stack the comparison: two columns of unequal length do not fit side by
       side on a phone, so each list gets its own label instead. */
    .compare-head { display: none; }
    .compare-body { grid-template-columns: 1fr; }
    .compare-mobile-label {
        display: block;
        padding: var(--space-4) var(--space-5);
        font-family: var(--font-headline);
        font-size: .95rem;
    }
    .compare-col--old .compare-mobile-label { background: rgba(255,255,255,.04); color: rgba(255,255,255,.55); }
    .compare-col--new .compare-mobile-label { background: rgba(34,197,94,.16); color: var(--color-primary-light); }
    .compare-item { padding: var(--space-4) var(--space-5); }

    /* Four ways: two up on phones rather than four squeezed columns. The CTA
       gives back some size here so the longest label, "Join as an affiliate",
       still breaks to two lines inside a half width card on a 360px screen. */
    .ways-grid { grid-template-columns: 1fr 1fr; gap: var(--space-4); }
    .way { padding: var(--space-5); gap: var(--space-3); }
    .way .btn { padding-inline: var(--space-3); font-size: .85rem; }
    .way-icon { width: 40px; height: 40px; flex: 0 0 40px; font-size: 1.2rem; }
    /* Matches the join card above it, so the two blocks line up. */
    .refer-panel { padding: 1.25rem; }
    .refer-row .btn { flex: 1 1 100%; }

    .cat-grid { grid-template-columns: 1fr; gap: var(--space-8); }
    .refer-rewards-grid { grid-template-columns: 1fr; }
    .cat-group h3 .material-symbols-outlined { width: 32px; height: 32px; flex: 0 0 32px; font-size: 1rem; }
}

/* =============================================================================
   SURVEY PAGE (/survey)
   Deliberately minimal: leaf mark, two instruments, one CTA. No nav, no hero.
   ============================================================================= */

.survey-page {
    position: relative;
    overflow: hidden;
    padding: var(--space-16) 0 var(--space-20);
    background: var(--color-surface);
}

/* The hidden attribute has to beat the panel/card display rules. */
.survey-page [hidden] { display: none !important; }

.survey-inner { max-width: 780px; }

.survey-brand {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .55rem;
    margin-bottom: var(--space-10);
}

.survey-title {
    font-family: var(--font-display);
    font-size: clamp(2.1rem, 6vw, 3.1rem);
    line-height: 1.1;
    text-align: center;
    color: var(--color-on-surface);
}

.survey-lede {
    max-width: 560px;
    margin: var(--space-4) auto 0;
    text-align: center;
    color: var(--color-on-surface-variant);
}

/* ---- Track picker ---- */

/* The public survey picker. TWO buttons, so one per row: full width, equal by
   definition, every label on a single line. Capped so they do not stretch into
   a wide band on a desktop screen. */
.survey-tabs {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-3);
    margin: var(--space-8) 0 var(--space-6);
}

@media (min-width: 561px) {
    .survey-tabs { max-width: 380px; margin-inline: auto; }
}

.survey-tab {
    padding: .8rem 1.4rem;
    border: 1px solid #dfe6e0;
    border-radius: var(--radius-full);
    background: var(--color-surface-elevated);
    font-family: var(--font-body);
    font-size: .95rem;
    font-weight: 600;
    line-height: 1.25;
    color: var(--color-on-surface-variant);
    text-align: center;
    cursor: pointer;
    transition: background 150ms ease, border-color 150ms ease, color 150ms ease;
}

.survey-tab:hover { border-color: var(--color-primary); color: var(--color-primary-darker); }

/* Admin filter bars. The visits and surveys pages reuse .survey-tab for the
   pill styling, but they are filters, not the two way picker on the public
   survey, so they lay out as a wrapping row that fills the admin column. They
   must NOT sit under .survey-tabs: that class is a single narrow column now,
   and putting these in it is what squashed the visits page into a 380px strip
   down the middle of a full width screen. */
.admin-tabs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-6);
}

.admin-tabs .survey-tab { padding: .55rem 1.1rem; font-size: .88rem; }

.admin-tabs .survey-tab-raw { margin-left: auto; }

.survey-tab.is-active {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: #fff;
    box-shadow: var(--shadow-green-glow);
}

.survey-blurb {
    margin-bottom: var(--space-8);
    text-align: center;
    color: var(--color-on-surface-variant);
}

/* ---- Questions ---- */

.survey-q {
    margin-bottom: var(--space-4);
    padding: var(--space-5);
    border: 1px solid #e6ebe7;
    border-radius: var(--radius-md);
    background: var(--color-surface-elevated);
}

.survey-q.is-required { border-left: 3px solid var(--color-primary); }

.survey-q-head {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
    margin-bottom: .35rem;
}

/* The badge and the text are siblings, not competitors. The text column gets
   all the remaining width, so the question runs to a readable measure instead
   of breaking after three or four words. */
.survey-q-text { flex: 1; min-width: 0; }
.survey-q-text .survey-q-label { display: block; }

.survey-q-num {
    display: inline-flex;
    flex: 0 0 26px;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    margin-top: 2px;   /* lines the badge up with the first line of the question */
    border-radius: 50%;
    background: var(--color-primary-dim);
    color: var(--color-primary-darker);
    font-size: .8rem;
    font-weight: 700;
}

.survey-q-label {
    font-family: var(--font-headline);
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--color-on-surface);
}

/* Sits under the question rather than out at the right hand edge. On a phone the
   right hand edge cost the question about 85px of width, and OPTIONAL is a note
   about the question, not a separate column. */
.survey-opt {
    display: block;
    margin-top: .3rem;
    font-size: .7rem;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--color-on-surface-inverse);
}

.survey-q-help {
    margin-bottom: var(--space-4);
    font-size: .85rem;
    color: var(--color-on-surface-muted);
}

.survey-textarea {
    min-height: 92px;
    padding: var(--space-4);
    font-size: .95rem;
    /* Radius, family, line-height and resize all come from textarea.input now. */
    padding-block: var(--space-4);
}

/* ---- Checkbox groups ---- */

.survey-checks {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-2);
}

.survey-check {
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    padding: .7rem .9rem;
    border: 1px solid #e6ebe7;
    border-radius: var(--radius-sm);
    font-size: .93rem;
    cursor: pointer;
    transition: background 120ms ease, border-color 120ms ease;
}

.survey-check:hover { border-color: var(--color-primary); background: var(--color-primary-dim); }
.survey-check:has(input:checked) { border-color: var(--color-primary); background: var(--color-primary-dim); }

.survey-check input {
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    margin-top: .2rem;
    accent-color: var(--color-primary-dark);
}

/* ---- Select "other" escape hatch ---- */

.survey-other {
    margin-top: var(--space-4);
    padding-top: var(--space-4);
    border-top: 1px dashed #e6ebe7;
}

.survey-other-label {
    display: block;
    margin-bottom: var(--space-2);
    font-size: .85rem;
    font-weight: 600;
    color: var(--color-on-surface-variant);
}

/* ---- Actions ---- */

.survey-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--space-4);
    margin-top: var(--space-6);
}

.survey-q-error {
    margin-top: var(--space-2);
    font-size: .82rem;
    color: var(--color-error);
}

.survey-q.has-error,
.survey-check.has-error,
.survey-checks.has-error {
    border-color: var(--color-error);
    box-shadow: 0 0 0 4px rgba(176, 37, 0, 0.08);
}

/* ---- Thank you ---- */

/* Roomier than the question cards: this is the end of the form, so it should
   feel like a landing rather than another box. */
.survey-done {
    max-width: 620px;
    margin: var(--space-8) auto 0;
    padding: var(--space-16) var(--space-10);
    border: 1px solid #e6ebe7;
    border-radius: var(--radius-lg);
    background: var(--color-surface-elevated);
    text-align: center;
}

/* The circle is one element and the glyph is a child, which is the pattern used
   everywhere else on the site. Putting .material-symbols-outlined on the circle
   itself lets that class fight the layout rules, and the glyph ends up parked in
   a corner instead of centred. */
.survey-done-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    margin-bottom: var(--space-5);
    border-radius: 50%;
    background: var(--color-primary-dim);
    color: var(--color-primary-dark);
    line-height: 1;
}

.survey-done-mark .material-symbols-outlined {
    font-size: 30px;
    line-height: 1;
    display: block;
}

.survey-done-title {
    font-family: var(--font-headline);
    font-size: clamp(1.5rem, 4vw, 2rem);
    color: var(--color-on-surface);
}

.survey-done-body {
    max-width: 460px;
    margin: var(--space-4) auto 0;
    color: var(--color-on-surface-variant);
    line-height: 1.7;
}

.survey-done-alt { margin-top: var(--space-8); }

.survey-linkbtn {
    border: none;
    background: none;
    font-family: var(--font-body);
    font-size: .95rem;
    font-weight: 600;
    color: var(--color-primary-dark);
    text-decoration: underline;
    cursor: pointer;
}

/* ---- Data use policy ---- */

/* Sits directly on the page background: no card, no border. Left aligned to
   the same edge as the panels above it, so only the text separates it. */
.survey-policy {
    margin-top: var(--space-10);
}

.survey-policy-title {
    font-family: var(--font-headline);
    font-size: 1.35rem;
    color: var(--color-on-surface);
    margin-bottom: var(--space-2);
}

.survey-policy-lead {
    font-weight: 600;
    color: var(--color-primary-darker);
}

.survey-policy-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin-top: var(--space-4);
    padding-left: 1.1rem;
}

.survey-policy-list li {
    font-size: .92rem;
    line-height: 1.6;
    color: var(--color-on-surface-variant);
}

.survey-policy-list a {
    font-weight: 600;
    color: var(--color-primary-dark);
    text-decoration: underline;
}

.survey-policy-link {
    margin-top: var(--space-4);
    text-align: center;
    font-size: .85rem;
}

.survey-policy-link a {
    color: var(--color-on-surface-muted);
    text-decoration: underline;
}

/* ---- Closing CTA ---- */

.survey-cta {
    margin-top: var(--space-12);
    padding: var(--space-10) var(--space-6);
    border-radius: var(--radius-lg);
    background: var(--color-ink);
    text-align: center;
}

.survey-cta-title {
    font-family: var(--font-headline);
    font-size: clamp(1.6rem, 4vw, 2.2rem);
    color: #fff;
}

.survey-cta-lede {
    max-width: 520px;
    margin: var(--space-3) auto var(--space-6);
    color: rgba(255, 255, 255, 0.72);
}

.survey-cta-back { margin-top: var(--space-5); font-size: .9rem; }
.survey-cta-back a { color: var(--color-primary-light); }

/* ---- Honeypot: off screen, never display:none (bots skip those) ---- */

.survey-hp {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* ---- Money field (USD) ---- */

.survey-money { position: relative; display: flex; align-items: center; }

.survey-money-prefix {
    position: absolute;
    left: 1.3rem;
    font-weight: 700;
    color: var(--color-on-surface-variant);
    pointer-events: none;
}

.survey-money-input { padding-left: 2.5rem; }

/* ---- 1 to 10 scale ---- */

.survey-scale {
    display: grid;
    grid-template-columns: repeat(10, 1fr);
    gap: .4rem;
}

.survey-scale-item { position: relative; display: block; }

.survey-scale-item input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.survey-scale-item span {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: .6rem 0;
    border: 1px solid #e6ebe7;
    border-radius: var(--radius-sm);
    font-size: .9rem;
    font-weight: 600;
    color: var(--color-on-surface-variant);
    cursor: pointer;
    transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}

.survey-scale-item span:hover { border-color: var(--color-primary); background: var(--color-primary-dim); }

.survey-scale-item input:checked + span {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: #fff;
}

.survey-scale-item input:focus-visible + span {
    outline: 2px solid var(--color-primary-dark);
    outline-offset: 2px;
}

@media (max-width: 720px) {
    .survey-page { padding: var(--space-10) 0 var(--space-16); }
    .survey-checks { grid-template-columns: 1fr; }
    .survey-scale { grid-template-columns: repeat(5, 1fr); }
    .survey-q { padding: var(--space-4); }
    .survey-actions { flex-direction: column; align-items: stretch; }
    .survey-actions .btn { width: 100%; }
    .survey-cta { margin-top: var(--space-10); padding: var(--space-8) var(--space-4); }
    .survey-done { padding: var(--space-10) var(--space-5); }
}

/* =============================================================================
   SKIP LINK
   First focusable thing in the document. Off screen until focused, then it
   drops into view at the top left.
   ============================================================================= */

.skip-link {
    position: absolute;
    top: 0;
    left: -9999px;
    z-index: 1000;
    padding: .8rem 1.4rem;
    background: var(--color-ink);
    color: #fff;
    font-weight: 600;
    border-radius: 0 0 var(--radius-sm) 0;
}

.skip-link:focus {
    left: 0;
    outline: 2px solid var(--color-primary-light);
    outline-offset: 2px;
}

/* =============================================================================
   KEYBOARD FOCUS ON FIELDS
   Declared last so it beats the component-level `outline: none` rules above.
   Inputs suppress the global halo because they draw their own ring.
   ============================================================================= */

.input:focus-visible,
.select:focus-visible,
textarea:focus-visible,
.input-group input:focus-visible {
    outline: 2px solid var(--color-panel-green);
    outline-offset: 2px;
    box-shadow: none;
}

/* =============================================================================
   LEGAL PAGES (privacy policy)
   The dark top band exists because the shared header is fixed and set in white,
   so it needs a dark surface to sit on until it gains its scrolled background.
   ============================================================================= */

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

.legal-hero {
    padding: calc(72px + var(--space-16)) 0 var(--space-12);
    background: var(--color-ink);
    color: #fff;
}

.legal-title {
    font-family: var(--font-display);
    font-size: clamp(2.2rem, 5vw, 3.2rem);
    line-height: 1.1;
    color: #fff;
}

.legal-lede {
    margin-top: var(--space-4);
    font-size: clamp(1.05rem, 1.6vw, 1.2rem);
    color: rgba(255, 255, 255, 0.72);
}

.legal-updated {
    margin-top: var(--space-4);
    font-size: .85rem;
    color: var(--color-primary-light);
}

.legal-body {
    padding: var(--space-16) 0 var(--space-20);
    background: var(--color-surface);
}

.legal-short {
    padding: var(--space-6);
    border-left: 3px solid var(--color-primary);
    border-radius: 0 var(--radius-md) var(--radius-md) 0;
    background: var(--color-primary-dim);
}

.legal-short-label {
    display: block;
    margin-bottom: var(--space-2);
    font-family: var(--font-headline);
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--color-primary-darker);
}

.legal-short p { color: var(--color-on-surface); font-weight: 600; }

.legal-section { margin-top: var(--space-12); }

.legal-section-title {
    margin-bottom: var(--space-3);
    font-family: var(--font-headline);
    font-size: 1.35rem;
    color: var(--color-on-surface);
}

.legal-section p {
    margin-bottom: var(--space-3);
    color: var(--color-on-surface-variant);
}

/* The global reset removes list markers, so they are restored here. */
.legal-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin: var(--space-3) 0 0;
    padding-left: 1.2rem;
    list-style: disc;
}

.legal-list li {
    font-size: .97rem;
    line-height: 1.65;
    color: var(--color-on-surface-variant);
}

.legal-contact {
    margin-top: var(--space-16);
    padding: var(--space-10) var(--space-6);
    border-radius: var(--radius-lg);
    background: var(--color-ink);
    text-align: center;
}

.legal-contact-title {
    font-family: var(--font-headline);
    font-size: clamp(1.5rem, 3.5vw, 2rem);
    color: #fff;
}

.legal-contact-body {
    margin-top: var(--space-3);
    color: rgba(255, 255, 255, 0.72);
}

.legal-contact-alt {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: .75rem;
    margin-top: var(--space-5);
    font-size: .9rem;
    color: rgba(255, 255, 255, 0.5);
}

.legal-contact-alt a { color: var(--color-primary-light); }

@media (max-width: 720px) {
    .legal-hero { padding: calc(72px + var(--space-10)) 0 var(--space-10); }
    .legal-body { padding: var(--space-12) 0 var(--space-16); }
    .legal-section { margin-top: var(--space-10); }
    .legal-contact { padding: var(--space-8) var(--space-4); }
}

/* =============================================================================
   9b. CONTENT INDEX (/content)
   =============================================================================
   Reuses .legal-hero and .legal-body for the band and the column, so the page
   sits in the same rhythm as /privacy. Only the things specific to an index of
   writing are defined here: the card grid, and the empty state that shows until
   there is something to put in it.
   ============================================================================= */

.content-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr));
    gap: var(--space-6);
}

.content-card {
    display: flex;
    flex-direction: column;
    gap: .625rem;
    padding: var(--space-6);
    border: 1px solid var(--color-surface-variant);
    border-radius: var(--radius-md);
    background: var(--color-surface-elevated);
    color: inherit;
    text-decoration: none;
    transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}

.content-card:hover,
.content-card:focus-visible {
    transform: translateY(-2px);
    border-color: var(--color-primary);
    box-shadow: var(--shadow-lg);
}

.content-card-kind {
    align-self: flex-start;
    padding: .25rem .625rem;
    border-radius: var(--radius-full);
    background: var(--color-primary-dim);
    color: var(--color-primary-darker);
    font-size: .75rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
}

.content-card-title {
    margin: 0;
    font-size: 1.25rem;
    line-height: 1.3;
}

.content-card-summary {
    margin: 0;
    color: var(--color-on-surface-variant);
    line-height: 1.6;
}

.content-card-meta {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    margin: auto 0 0;
    padding-top: .25rem;
    color: var(--color-on-surface-variant);
    font-size: .85rem;
}

/* The empty state. A dashed edge rather than a solid one, so it reads as a
   space waiting to be filled instead of a card that failed to load. */
.content-empty {
    padding: var(--space-12) var(--space-6);
    border: 1px dashed var(--color-surface-variant);
    border-radius: var(--radius-md);
    text-align: center;
}

.content-empty-icon {
    font-size: 2.5rem;
    color: var(--color-primary);
}

.content-empty-title {
    margin: var(--space-4) 0 0;
    font-size: 1.5rem;
}

.content-empty-body {
    max-width: 34rem;
    margin: var(--space-3) auto 0;
    color: var(--color-on-surface-variant);
    line-height: 1.7;
}

.content-empty-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: .75rem;
    margin-top: var(--space-6);
}

@media (max-width: 720px) {
    .content-card { padding: var(--space-5); }
    .content-empty { padding: var(--space-10) var(--space-5); }
}

/* =============================================================================
   10. CLIENT ACCOUNT PAGES (/dev)
   ============================================================================= */

/* The top band is dark on purpose, for the same reason as .legal-hero: the
   shared header is fixed and uses white text, so it needs a dark surface to sit
   on until it gains its scrolled background. The top padding clears the 72px
   header. */
.client-hero {
    padding: calc(72px + var(--space-16)) 0 var(--space-12);
    background: var(--color-ink);
    color: #fff;
}

/* A hero decal that must not be chopped.
   The band carries .has-decal, which is overflow: hidden, so a decal taller than
   the band is cut off rather than allowed to spill. client_hero() writes an exact
   max-height for the decal's own top offset; object-fit then scales the artwork
   down inside that box instead of squashing it, and object-position keeps it
   pinned top right so capping changes the size and nothing else.
   max-width is the same idea sideways, for a narrow viewport. */
.client-hero .decal-fit {
    max-width: calc(100% - 10%);
    object-fit: contain;
    object-position: top right;
}

.client-body {
    padding: var(--space-16) 0 var(--space-20);
    background: var(--color-surface);
}

@media (max-width: 720px) {
    .client-hero { padding: calc(72px + var(--space-10)) 0 var(--space-10); }
    .client-body { padding: var(--space-12) 0 var(--space-16); }
}

/* =============================================================================
   THE PARTNER JOIN FORM (/dev/join)
   -----------------------------------------------------------------------------
   Two tracks. Each one is a heading block, a full width name field, and one or
   more checklists. The heading block used to sit flush against the first field
   with no gap at all, which made the whole group read as one dense lump; it now
   has real space under it and a lede line that explains what the group is for.
   ============================================================================= */

.partner-track {
    margin-top: var(--space-8);
    padding-top: var(--space-8);
    border-top: 1px solid var(--color-outline);
}

/* The heading over a form card.
   The shared .section-head carries no bottom margin at all, because the marketing
   sections that use it put their own space under it. Here the next thing is a card
   with no top margin of its own, so the title and its lede sat directly on top of
   it. This gives the title room under it, and the block room above the card. */
.section-head-form { margin-bottom: var(--space-10); }
.section-head-form h2 { line-height: 1.1; }
.section-head-form .lede { margin-top: var(--space-5); }

/* The heading block inside a track. */
.partner-head { margin-bottom: var(--space-8); }

.partner-head-title {
    display: flex;
    align-items: center;
    gap: .55rem;
    margin: 0;
    font-family: var(--font-headline);
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--color-on-surface);
}
.partner-head-title .material-symbols-outlined {
    font-size: 1.3rem;
    color: var(--color-primary-dark);
}

.partner-head-lede {
    margin: .75rem 0 0;
    font-size: .9rem;
    line-height: 1.55;
    color: var(--color-on-surface-variant);
}

/* A named group of checkboxes. fieldset, so the legend labels the group for a
   screen reader rather than only looking like a heading. */
.partner-set {
    margin: var(--space-8) 0 0;
    padding: 0;
    border: 0;
    min-width: 0;
}
.partner-set-title {
    padding: 0;
    font-family: var(--font-headline);
    font-size: 1rem;
    font-weight: 700;
    color: var(--color-on-surface);
}
.partner-set-lede {
    margin: .4rem 0 var(--space-4);
    font-size: .87rem;
    line-height: 1.55;
    color: var(--color-on-surface-variant);
}

/* One sub-group inside a checklist, for the eight industry headings. */
.partner-group + .partner-group { margin-top: var(--space-5); }
.partner-group-title {
    display: block;
    margin-bottom: .55rem;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--color-primary-dark);
}

/* =============================================================================
   THE HERO BAND AS A CONTROL SURFACE (/dev)
   -----------------------------------------------------------------------------
   The client home puts real UI in the dark band: the title with its action button,
   then the search, then the filters. The white area below is left to results.
   These are the pieces that make that fit on one dark surface, compactly.
   ============================================================================= */

/* A left aligned hero head. The default hero head is centred, which is right for a
   page that is only a title and wrong for one with a form under it: a centred title
   over a full width search bar reads as two unrelated things. */
.hero-head-left { text-align: left; margin-inline: 0; }
.hero-head-left .badge { margin-inline: 0; }

/* Everything the page passed into the hero's content slot. */
.hero-slot { margin-top: var(--space-10); }

/* Title on the left, action on the right, one line. */
.hero-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-5);
    min-width: 0;
}
.hero-row > * { min-width: 0; }

/* The title row and the search are one compact block: the search sits closer than
   a full section gap, because together they are the whole band. */
.hero-row + .hero-row { margin-top: var(--space-6); }

/* Heading and lede on the left, action on the right, all on one line. The lede sits
   under the heading inside this block, so the button aligns to the block's middle
   rather than to the heading's baseline. */
.hero-row-main { flex: 1 1 420px; }

/* The two headings inside the band. Smaller than the page title above them, and
   tighter than the white-area headings they replaced, because the band has to hold
   a title, a button, a search bar and four filter groups without becoming a wall. */
.hero-h2 {
    margin: 0;
    font-family: var(--font-headline);
    font-size: clamp(1.35rem, 2.4vw, 1.8rem);
    font-weight: 700;
    line-height: 1.2;
    color: #fff;
}

.hero-sub {
    margin: .5rem 0 0;
    font-size: .95rem;
    line-height: 1.55;
    color: rgba(255, 255, 255, .65);
}

.hero-cta { flex: 0 0 auto; }

/* The search owns its row, so it takes the whole width. */
.hero-row-search { display: block; }

/* The dark variants of the shared controls. The marketing form controls are built
   for a white page, so on ink they need their own background, border and text or
   they read as holes punched in the band. */
.input-dark,
.select-dark {
    background: rgba(255, 255, 255, .06);
    border-color: rgba(255, 255, 255, .16);
    color: #fff;
}
.input-dark::placeholder { color: rgba(255, 255, 255, .45); }
.input-dark:focus,
.select-dark:focus {
    border-color: var(--color-primary);
    box-shadow: 0 0 0 4px rgba(34, 197, 94, .18);
}
.select-dark option { color: var(--color-on-surface); background: #fff; }

/* The results grid sits inside the white band with no sidebar beside it now. */
.wire-grid-results { margin-top: 0; }

/* ---- The logo slot, in the details panel ----
   Sits opposite the heading, on the same row. It holds the shared placeholder mark
   until an upload exists, and the same mark serves a business and an affiliate, so
   there is one file rather than one each.

   It sits in the details panel, on white, so the plate it needed on ink is gone. The
   artwork keeps a hairline outline instead, so a grey mark on a white panel still
   reads as a deliberate placeholder rather than a washed out image.

   It is a <button> because clicking it is meant to open an upload. The upload is not
   built, so the button is disabled and carries a title saying so rather than
   pretending. The real editing area is the next piece of work. */
.track-logo {
    display: block;
    width: 72px;
    height: 72px;
    padding: 0;
    border: 1px solid var(--color-outline);
    border-radius: var(--radius-md);
    overflow: hidden;
    background: var(--color-surface);
    cursor: pointer;
}

.track-logo img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* Disabled until the upload exists. Dimmed, and the cursor says so, so it cannot be
   mistaken for a control that works. */
.track-logo-empty { cursor: not-allowed; }
.track-logo-empty img { opacity: .8; }

/* The edit button keeps its own position at the end of the row. */
.track-panel-edit { flex: 0 0 auto; }

/* Inside the panel the logo is the first thing on the row, then the name, then the
   edit button. The name takes the slack so the button stays right aligned. */
.track-panel-head .track-logo {
    flex: 0 0 auto;
    width: 72px;
    height: 72px;
}

.track-panel-id { flex: 1 1 auto; }

/* =============================================================================
   A TRACK YOU ALREADY HOLD, on the join page
   -----------------------------------------------------------------------------
   Replaces the checkbox and the whole field group for that track. There is nothing
   to tick and nothing to save, so it is a link to the page that owns it, carrying the
   name it was saved under so the answer to "have I done this already" is on the page.
   ============================================================================= */

.join-held {
    display: grid;
    gap: var(--space-3);
    margin-bottom: var(--space-6);
}

.join-held-item {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-4) var(--space-5);
    border: 1px solid var(--color-outline);
    border-radius: var(--radius-md);
    background: var(--color-surface-elevated);
    text-align: left;
    transition: border-color 150ms ease, transform 150ms ease;
}
.join-held-item:hover {
    border-color: var(--color-primary);
    transform: translateY(-1px);
}

/* The icon box. Written the way .way-icon is written, and for the same reason: the
   box is one element and the icon font is another. Putting both classes on ONE element
   lets display:inline-block from the icon font beat display:inline-flex here, which
   pins the glyph to the top-left of a box that then shows no background at all. */
.join-held-icon {
    flex: 0 0 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: var(--radius-sm);
    background: var(--color-primary-dim);
    color: var(--color-primary-dark);
}
.join-held-icon .material-symbols-outlined {
    display: block;
    line-height: 1;
    font-size: 22px;
}

/* ARE YOU BOTH?
   The prompt shown when one track is held and the other could still be joined. It sits
   above the checkbox, and the checkbox is the same control a new visitor gets. */
.join-both {
    margin-bottom: var(--space-7);
    text-align: center;
}
.join-both-ask {
    margin: 0;
    font-family: var(--font-headline);
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--color-on-surface);
}
.join-both-lede {
    margin: var(--space-2) auto var(--space-5);
    max-width: 46ch;
    font-size: .9rem;
    line-height: 1.55;
    color: var(--color-on-surface-muted);
}

.join-held-body { flex: 1 1 auto; min-width: 0; }
.join-held-label {
    display: block;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--color-on-surface-muted);
}
.join-held-name {
    display: block;
    margin-top: .15rem;
    font-family: var(--font-headline);
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--color-on-surface);
    overflow-wrap: anywhere;
}

.join-held-go {
    flex: 0 0 auto;
    color: var(--color-primary-dark);
    transition: transform 150ms ease;
}
.join-held-item:hover .join-held-go { transform: translateX(3px); }

/* =============================================================================
   THE CONFIRMATION DIALOG
   -----------------------------------------------------------------------------
   Taken from the modal already built for enterramon (enterramon/myReport.php): the
   same .screenshot-modal shell, the same .modal-backdrop with its blur, the same
   fixed centred panel. Adapted in three ways:
     - the panel is a card on white rather than a screenshot viewer, because this one
       holds words and controls
     - it is 1000 rather than 10001, which is above everything on the page and below
       the sticky header's own layering
     - it is dismissible: click the backdrop, press Escape, or use a button
   ============================================================================= */

.screenshot-modal {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-4);
    outline: none;
    scroll-behavior: auto;
}

.screenshot-modal[hidden] { display: none; }

.modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, .85);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}

.modal-panel {
    position: relative;
    width: 100%;
    max-width: 520px;
    max-height: 85vh;
    overflow-y: auto;
    padding: var(--space-6);
    border-radius: var(--radius-md);
    background: var(--color-surface-elevated);
    box-shadow: 0 20px 50px rgba(0, 0, 0, .5);
    text-align: left;
}

.modal-title {
    margin: 0 0 var(--space-3);
    font-family: var(--font-headline);
    font-size: 1.3rem;
    font-weight: 700;
    color: var(--color-on-surface);
}

.modal-body {
    margin: 0 0 var(--space-5);
    font-size: .95rem;
    line-height: 1.6;
    color: var(--color-on-surface-variant);
}

.modal-list {
    margin: 0 0 var(--space-5);
    padding: 0;
    list-style: none;
}

.modal-list li {
    display: flex;
    align-items: flex-start;
    gap: .55rem;
    margin-bottom: var(--space-2);
    font-size: .92rem;
    color: var(--color-on-surface-variant);
}
.modal-list li .material-symbols-outlined {
    flex: 0 0 auto;
    font-size: 18px;
    color: var(--color-error);
    margin-top: .1rem;
}

.modal-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-3);
}

/* Body scroll lock while a dialog is open, put on by admin.js and removed on close.
   Without it the page behind scrolls under the backdrop, which reads as the dialog
   drifting. */
body.modal-open { overflow: hidden; }

/* =============================================================================
   THE BUSINESS PROFILE EDITOR (/dev/business/edit)
   ============================================================================= */

.profile-form { text-align: left; }

/* A fieldset per section: a title, a line saying what it is for, then the fields.
   fieldset rather than a div so the legend labels the group for a screen reader. */
.profile-set {
    margin: 0 0 var(--space-8);
    padding: var(--space-8);
    border: 1px solid #e6ebe7;
    border-radius: var(--radius-md);
    background: var(--color-surface-elevated);
    min-width: 0;
}
.profile-set-title {
    padding: 0;
    font-family: var(--font-headline);
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--color-on-surface);
}
.profile-set-lede {
    margin: .4rem 0 var(--space-5);
    font-size: .87rem;
    line-height: 1.55;
    color: var(--color-on-surface-variant);
}
/* Spacing between the blocks inside a section.
   This used to be a list of adjacent-sibling pairs (.field + .field, .grid + .field),
   which breaks the moment anything else sits between two of them: the industries note
   was inserted between two fields, the adjacency was broken, and both sides collapsed
   to zero. Lobotomised owl instead, so a block is spaced from whatever precedes it
   regardless of what that is. */
.profile-set > * + * { margin-top: var(--space-6); }
.profile-set .grid { gap: var(--space-5); }

/* The logo pick: the whole frame is the label, so clicking the image opens the
   picker with no script involved. */
.profile-logo-row {
    display: flex;
    align-items: center;
    gap: var(--space-5);
    flex-wrap: wrap;
}
.profile-logo-pick {
    flex: 0 0 auto;
    width: 96px;
    height: 96px;
    cursor: pointer;
}
.profile-logo-pick:hover { border-color: var(--color-primary); }
.profile-logo-pick img { width: 100%; height: 100%; object-fit: contain; }
.profile-logo-copy { flex: 1 1 240px; min-width: 0; }

/* A file input styled as nothing, since its label is the thing you see. Kept in the
   DOM and focusable: hiding it with display:none would take it out of the tab order
   and make the picker unreachable by keyboard. */
.visually-hidden-file {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}
.profile-logo-pick:focus-within {
    outline: 3px solid var(--color-primary);
    outline-offset: 3px;
}

/* A fieldset-style label that is NOT a <label>, for a group of checkboxes.
   .field label is styled for a single control; a checklist needs a heading that is
   not tied to one input. */
.field-legend {
    display: block;
    margin-bottom: var(--space-2);
    font-weight: 600;
    font-size: .9rem;
    color: var(--color-on-surface-variant);
}

/* A LINK PER CHANNEL. One row per ticked channel, revealed by the script; without
   script they are all shown, which is the honest fallback. */
.channel-links {
    display: grid;
    gap: var(--space-4);
    margin-top: var(--space-4);
}
.channel-link {
    display: grid;
    grid-template-columns: 150px minmax(0, 1fr);
    align-items: center;
    gap: var(--space-4);
}
.channel-link[hidden] { display: none; }
.channel-link label {
    font-weight: 600;
    font-size: .9rem;
    color: var(--color-on-surface-variant);
}
@media (max-width: 640px) {
    .channel-link { grid-template-columns: 1fr; gap: var(--space-2); }
}

/* A value shown rather than offered for editing. Deliberately NOT styled as an input:
   a read-only field that looks editable is a field people try to type in. */
.profile-fixed {
    margin: 0;
    padding: var(--space-3) var(--space-5);
    border: 1px dashed var(--color-outline);
    border-radius: var(--radius-full);
    background: var(--color-surface);
    font-size: 1rem;
    color: var(--color-on-surface);
    overflow-wrap: anywhere;
}

/* The address. Two columns on a wide form, one on a narrow one, with the street line
   across the full width because it is the longest thing anybody types. */
.address-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-4);
    margin-top: var(--space-4);
}
.address-grid .address-full { grid-column: 1 / -1; }

/* The public-address tick box sits under the address grid, on its own line rather than in
   a column, because it is a decision about the whole address rather than a part of it. */
.profile-choice { margin-top: var(--space-5); }
@media (max-width: 640px) {
    .address-grid { grid-template-columns: minmax(0, 1fr); }
}

/* A label with its character counter on the same line, the label left and the count
   right, so the count does not push the label or wrap under it. */
.field-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-3);
}
.field-count {
    flex: 0 0 auto;
    font-size: .78rem;
    font-variant-numeric: tabular-nums;   /* so the number does not jiggle as it counts */
    color: var(--color-on-surface-muted);
}
/* Near the limit it warns, and past it it is an error. The input stops accepting at
   maxlength anyway, so `over` should be unreachable: it is there for a paste. */
.field-count.is-near { color: #8a6d00; }
.field-count.is-over { color: var(--color-error); font-weight: 700; }

.profile-help {
    margin: 0;
    font-size: .84rem;
    color: var(--color-on-surface-muted);
}

/* The image grid: existing images and the local preview use the same shape, so what
   you picked looks like what you will get. */
.profile-media {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: var(--space-4);
    margin-top: var(--space-4);
}
.profile-media-item {
    position: relative;
    margin: 0;
    border: 1px solid var(--color-outline);
    border-radius: var(--radius-sm);
    overflow: hidden;
    background: var(--color-surface);
}
.profile-media-item img {
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
}
.profile-media-item.is-missing { border-style: dashed; }
.profile-media-gone {
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 1 / 1;
    font-size: .8rem;
    color: var(--color-error);
    text-align: center;
    padding: var(--space-3);
}
.profile-media-name {
    padding: .4rem .55rem;
    font-size: .72rem;
    color: var(--color-on-surface-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.profile-media-remove {
    display: flex;
    align-items: center;
    gap: .4rem;
    padding: .45rem .55rem;
    border-top: 1px solid var(--color-outline);
    font-size: .78rem;
    color: var(--color-on-surface-variant);
    cursor: pointer;
}
.profile-media-remove:has(input:checked) {
    background: rgba(176, 37, 0, .08);
    color: var(--color-error);
}

/* The lock note beside the field it explains: green left accent, because it is
   information about how to change something rather than a warning. */
.profile-locked {
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    /* A block, not a field, so it takes the section's own spacing rather than the
       label gap a .field would apply. */
    margin-bottom: 0;
    padding: var(--space-4);
    border-left: 3px solid var(--color-primary);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    background: var(--color-primary-dim);
}
.profile-locked .material-symbols-outlined {
    flex: 0 0 auto;
    font-size: 18px;
    color: var(--color-primary-dark);
    margin-top: .1rem;
}
.profile-locked-title {
    display: block;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--color-primary-dark);
    margin-bottom: .25rem;
}
.profile-locked-text {
    margin: 0;
    font-size: .9rem;
    line-height: 1.55;
    color: var(--color-on-surface-variant);
}

/* The danger zone. A tinted panel rather than a red one: it should read as a
   separate, serious section, not as an error state. */
.profile-set-danger {
    border-color: rgba(176, 37, 0, .25);
    background: rgba(176, 37, 0, .03);
}
.profile-set-danger .profile-set-title { color: var(--color-error); }

.profile-note {
    margin: 0;
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    font-size: .87rem;
    color: var(--color-on-surface-muted);
}

.profile-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
}

/* The tagline under the name, and the profile blocks on the read view. */
.track-panel-tagline {
    margin: .3rem 0 0;
    font-size: .92rem;
    line-height: 1.5;
    color: var(--color-on-surface-variant);
}

.track-panel-para {
    margin: 0 0 var(--space-4);
    font-size: .95rem;
    line-height: 1.65;
    color: var(--color-on-surface-variant);
}
.track-panel-para:last-child { margin-bottom: 0; }

.track-address {
    display: flex;
    align-items: flex-start;
    gap: .5rem;
}
.track-address .material-symbols-outlined {
    flex: 0 0 auto;
    font-size: 18px;
    color: var(--color-primary-dark);
    margin-top: .15rem;
}

.track-contact {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-6);
}
.track-contact-link {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    font-size: .92rem;
    color: var(--color-primary-dark);
    overflow-wrap: anywhere;
}
.track-contact-link:hover { text-decoration: underline; }
.track-contact-link .material-symbols-outlined { font-size: 18px; }

/* The work images. A plain grid, three across on a wide panel and fewer as it
   narrows, with a square crop so a mixed set of shapes still lines up. */
/* WHERE TO FIND THEM: one row per channel, the link ones clickable. */
.track-channels {
    display: grid;
    gap: var(--space-3);
}
.track-channel {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--color-outline);
    border-radius: var(--radius-sm);
    background: var(--color-surface-elevated);
    min-width: 0;
}
.track-channel .material-symbols-outlined {
    flex: 0 0 auto;
    font-size: 18px;
    color: var(--color-primary-dark);
}
.track-channel-name {
    flex: 0 0 auto;
    font-weight: 600;
    font-size: .92rem;
    color: var(--color-on-surface);
}
.track-channel-url {
    flex: 1 1 auto;
    min-width: 0;
    text-align: right;
    font-size: .85rem;
    color: var(--color-on-surface-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
a.track-channel:hover { border-color: var(--color-primary); }
.track-channel.is-plain { background: var(--color-surface); }
.track-channel.is-plain .track-channel-name { color: var(--color-on-surface-muted); }

.track-media {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: var(--space-3);
}
.track-media-item {
    margin: 0;
    border-radius: var(--radius-sm);
    overflow: hidden;
    background: var(--color-surface);
    border: 1px solid var(--color-outline);
}
.track-media-item img {
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
}

/* ---- One joined track, read back (/dev/business, /dev/affiliation) ----
   A single panel: what they are known by and a way to edit, then their answers as
   chips. Deliberately plain. It is a summary of a form they have already filled in,
   not a second form. */
/* Also give the /dev footer its own hook. It keeps .site-footer's classes so the
   styling carries over, and .dev-footer is where /dev can differ later without
   touching the marketing footer. */
.dev-footer { /* intentionally inherits .site-footer */ }

.track-panel {
    padding: var(--space-6);
    border: 1px solid #e6ebe7;
    border-radius: var(--radius-md);
    background: var(--color-surface-elevated);
}

.track-panel-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    min-width: 0;
}
.track-panel-head > * { min-width: 0; }

.track-panel-label {
    display: block;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--color-primary-dark);
}

.track-panel-value {
    margin: .35rem 0 0;
    font-family: var(--font-headline);
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--color-on-surface);
    overflow-wrap: anywhere;
}

.track-panel-list {
    margin-top: var(--space-6);
    padding-top: var(--space-5);
    border-top: 1px solid var(--color-outline);
}

.track-panel-list-title {
    margin-bottom: var(--space-3);
    font-family: var(--font-headline);
    font-size: .95rem;
    font-weight: 700;
    color: var(--color-on-surface);
}

/* The compact chip. 64 industries have to fit without the page turning into a
   wall, so this is the same .choice at a smaller padding and type size.

   THE BOX IS NOT SHRUNK WITH THE CHIP. It used to drop to 15px, and on a pale chip
   against pale text a 15px native box reads as a speck, or as nothing at all when the
   chip is tinted because it is ticked. The chip gets smaller; the control does not.
   A tick box that is hard to see is a tick box people miss. */
.choice-sm {
    gap: .5rem;
    padding: .45rem .7rem;
    font-size: .85rem;
}
.choice-sm input[type="checkbox"],
.choice-sm input[type="radio"] {
    width: 18px;
    height: 18px;
}

/* The invalid state.
   A single field gets aria-invalid from the script, which used to change nothing
   visible and only moved the focus. A checklist is a fieldset, not one input, so
   the script marks the group instead and the heading carries the colour. */
.input[aria-invalid="true"],
.select[aria-invalid="true"] {
    border-color: var(--color-error);
    box-shadow: 0 0 0 4px rgba(176, 37, 0, 0.08);
}
.partner-set.is-invalid .partner-set-title { color: var(--color-error); }
.partner-set.is-invalid .choice { border-color: color-mix(in srgb, var(--color-error) 45%, transparent); }

/* ---- Dev-area header ----
   The same .site-header shell as the marketing nav, so the sticky background,
   the mobile panel and the burger all keep working through site.js, but with
   the client area's own items and an account icon instead of the six marketing
   links and the wait-list button. */
.client-header .nav-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    flex: 0 0 40px;
    border: 1px solid rgba(255, 255, 255, .18);
    border-radius: 50%;
    color: rgba(255, 255, 255, .82);
    transition: background .2s ease, border-color .2s ease, color .2s ease;
}
.client-header .nav-icon:hover {
    background: rgba(255, 255, 255, .08);
    border-color: rgba(255, 255, 255, .32);
    color: #fff;
}
/* The glyph stays nested. An icon-font element must never also carry a sizing
   or layout class, or it pins itself to the top-left of the box. */
.client-header .nav-icon .material-symbols-outlined {
    display: block;
    line-height: 1;
    font-size: 1.4rem;
}

/* The signed-in identity: the account icon with the nickname beside it. The name
   is truncated rather than allowed to shove the action button off the bar. */
.client-header .nav-user {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    min-width: 0;
}
.client-header .nav-user-name {
    max-width: 14ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
    font-size: .92rem;
    color: rgba(255, 255, 255, .88);
}

/* The notification placeholder is a <button>, so the browser defaults have to go
   before .nav-icon's circle can take over. */
.client-header button.nav-icon {
    background: none;
    padding: 0;
    font: inherit;
    cursor: pointer;
}
.client-header .nav-icon:disabled {
    opacity: .45;
    cursor: not-allowed;
}
.client-header .nav-icon:disabled:hover {
    background: none;
    border-color: rgba(255, 255, 255, .18);
    color: rgba(255, 255, 255, .82);
}

/* On a phone the panel is a column. The action button takes a line of its own,
   and the identity and the bell share the line above it.
   The identity is LAST in the markup, so that it lands on the far right of the
   desktop bar past the action button. That is the wrong place on a phone, so the
   visual order is put back here with `order`. Order is cosmetic: the tab order
   still follows the DOM. */
@media (max-width: 720px) {
    .client-header .nav-cta { flex-wrap: wrap; }
    .client-header .nav-user { order: 1; }
    .client-header .nav-cta > .nav-icon { order: 2; }
    .client-header .nav-cta .btn { order: 3; width: 100%; flex: 1 1 100%; }
}

/* ---- Account page ----
   The account details sit straight on the page: no card, no border and no
   background, so the only things with weight are the actions. */
.account-details {
    text-align: left;
}

/* The phone prompt. The control is disabled on purpose: the verification flow
   is not built, and a button that looks live but does nothing is worse than one
   that says so. */
.account-verify {
    margin-bottom: var(--space-10);
    text-align: center;
}

.account-incomplete {
    display: block;
    margin-top: var(--space-2);
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .04em;
    color: var(--color-on-surface-inverse);
}

/* One row of actions, every control the same height.
   The label buttons are pinned to --account-control with their vertical padding
   dropped, and the icon buttons are that height and square. Without this the
   primary (btn-lg), the secondary and the 48px circles were three different
   heights sitting on one baseline. */
.account-actions {
    --account-control: 52px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
    margin-top: var(--space-10);
}

.account-actions .btn {
    height: var(--account-control);
    min-height: var(--account-control);
    padding-top: 0;
    padding-bottom: 0;
}

/* The main action takes the room that is left, so it reads as the primary. */
.account-actions-main {
    flex: 1 1 240px;
}

.btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    flex: 0 0 52px;
    padding: 0;
    border-radius: 50%;
}
.btn-icon .material-symbols-outlined { display: block; line-height: 1; font-size: 1.35rem; }
.btn-icon:disabled { opacity: .45; cursor: not-allowed; transform: none; box-shadow: none; }

/* =============================================================================
   .circle-button — A BUTTON THAT IS ACTUALLY ROUND
   =============================================================================
   A ROUND BUTTON NEEDS A SQUARE BOX. That is the whole of it, and it is why .btn
   alone does not do it.

   .btn already carries `border-radius: var(--radius-full)` (9999px), which reads
   as "round" and is not: a large radius on a box that is wider than it is tall
   gives a PILL, and a pill is what every icon button here had been getting. The
   radius was never the problem. The box is.

   enterramon gets a true circle from the same 9999px radius because its glyph box
   is square — it sets `font-size: 1.25rem` AND `line-height: 1.25rem` on
   .material-symbols-outlined, so the icon's inline box is 1.25rem by 1.25rem and
   8px of padding around a square is still a square. Here the icon uses
   `line-height: 1`, so the box is only square by luck; anything that adds a
   descender or a wider glyph turns the button back into a pill.

   THIS CLASS STOPS RELYING ON THE CONTENT. It pins the box to equal width and
   height and gives it 50% — a circle degenerates into an ellipse only when the box
   is not square, so with the box pinned square the radius cannot be wrong. One
   glyph, no glyph, it is a circle.

   --circle-size IS THE KNOB. 2.5rem by default: a comfortable click target beside
   a 2.25rem input, and small enough not to tower over one — which is what the 52px
   .btn-icon was doing on the hours row. Set it inline for another size rather than
   writing a second class.

   ICON-ONLY, BY DEFINITION. A circle has room for one glyph. A button with a word
   in it wants the pill .btn already gives. */
.circle-button {
    --circle-size: 2.5rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--circle-size);
    height: var(--circle-size);
    flex: 0 0 var(--circle-size);
    padding: 0;
    border-radius: 50%;
    line-height: 1;
}

/* The glyph is centred by the flex box, so it does not need a square line box of
   its own. Sizing it here keeps every circle-button's icon the same weight
   whatever font-size it would otherwise inherit. */
.circle-button .material-symbols-outlined {
    display: block;
    font-size: 1.25rem;
    line-height: 1;
}

.circle-button:disabled { opacity: .45; cursor: not-allowed; transform: none; }

/* The rule that closes off the actions, and the note underneath it. */
.account-rule {
    margin: var(--space-10) 0 var(--space-8);
    border: 0;
    border-top: 1px solid var(--color-surface-variant);
}

.account-about {
    text-align: left;
}
.account-about-text {
    max-width: 58ch;
    color: var(--color-on-surface-variant);
}
.account-about-age {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    margin-top: var(--space-5);
}
.account-about-age-value {
    font-family: var(--font-headline);
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--color-on-surface);
}
.account-about-age-label {
    font-size: .8rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--color-on-surface-inverse);
}

/* Deleting is destructive, so it sits apart from the everyday actions and below
   the note, not in the row with them. */
.account-danger {
    margin-top: var(--space-8);
    text-align: left;
}
.btn-danger {
    background: transparent;
    color: var(--color-error);
    border: 1px solid currentColor;
}
.btn-danger:hover { background: rgba(176, 37, 0, .06); transform: none; }
.account-danger .btn:disabled { opacity: .5; cursor: not-allowed; }

/* A DISABLED BUTTON MUST LOOK DISABLED, EVERYWHERE.
   The rule above only covers buttons inside .account-danger, so every other disabled
   .btn on the site looked completely normal: the close dialog's confirm button was
   disabled until the address was typed back, looked ready, and clicking it did
   nothing. That reads as a broken button rather than as a gate.
   This is on .btn itself so no page has to remember. */
.btn:disabled,
.btn[disabled] {
    opacity: .55;
    cursor: not-allowed;
}
.btn:disabled:hover,
.btn[disabled]:hover {
    /* No hover effect on something that cannot be clicked: a button that lights up
       under the cursor is a promise it will do something. */
    transform: none;
    box-shadow: none;
}

/* =============================================================================
   11. CLIENT HOME WIREFRAME (/dev)
   =============================================================================
   Structure only. The guest home has two blocks: post something you need done,
   and find somebody who can do it. The search block is a bar over a sidebar and
   a three-wide grid.

   The card bodies are skeleton placeholders on purpose. There is no business
   data yet, and a grid of realistic-looking fake businesses reads as real data
   in a way a wireframe must not.
   ============================================================================= */

.wire-block + .wire-block { margin-top: var(--space-12); }

.wire-block-head { margin-bottom: var(--space-6); text-align: left; }
.wire-block-head h3 { font-family: var(--font-headline); font-weight: 700; }

/* Search bar: the field takes the room, the category select is fixed, and the
   button sits at the end. */
.wire-search {
    display: grid;
    grid-template-columns: 1fr minmax(180px, 240px) auto;
    gap: var(--space-3);
    align-items: center;
}
.wire-search .input,
.wire-search .select,
.wire-search .btn { height: 52px; }

/* Sidebar plus grid. */
.wire-layout {
    display: grid;
    grid-template-columns: 240px 1fr;
    gap: var(--space-8);
    margin-top: var(--space-8);
    align-items: start;
}

.wire-filters {
    padding: var(--space-5);
    border: 1px solid var(--color-surface-variant);
    border-radius: var(--radius-md);
    text-align: left;
}
.wire-filters h4 {
    margin-bottom: var(--space-4);
    font-size: .8rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--color-on-surface-inverse);
}
.wire-filter-group + .wire-filter-group {
    margin-top: var(--space-6);
    padding-top: var(--space-5);
    border-top: 1px solid var(--color-surface-variant);
}
.wire-filter-group h5 {
    margin-bottom: var(--space-3);
    font-size: .9rem;
    font-weight: 700;
    color: var(--color-on-surface);
}
/* Plain checkboxes: no box around each option. The FILTER panel keeps its own
   outline, so the sidebar still reads as a panel, but the eight categories do
   not each draw a second border inside it.
   Deliberately NOT shared with .survey-check: the survey keeps its option chips. */
.wire-check {
    display: flex;
    align-items: flex-start;
    gap: .55rem;
    padding: .3rem 0;
    font-size: .88rem;
    line-height: 1.35;
    color: var(--color-on-surface-variant);
    cursor: pointer;
}
.wire-check input {
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    margin-top: .1rem;
    accent-color: var(--color-primary-dark);
}
.wire-check:has(input:checked) { color: var(--color-on-surface); }

/* Disabled while this is a wireframe, so it must not invite a click. */
.wire-check:has(input:disabled) { cursor: default; color: var(--color-on-surface-inverse); }
.wire-check input:disabled { opacity: .55; cursor: not-allowed; }

/* Only the plain text field is inert. */
.wire-filters input[type="text"] { pointer-events: none; opacity: .7; }

/* Three wide, and it stays three wide all the way down to the tablet break. */
.wire-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-5);
}

.wire-card {
    padding: var(--space-5);
    border: 1px solid var(--color-surface-variant);
    border-radius: var(--radius-md);
    background: #fff;
    text-align: left;
}
/* A grey block standing in for something that will be real. `display: block` so
   the spans take the width and height they are given. */
.wire-skel {
    display: block;
    background: var(--color-surface-variant);
    border-radius: var(--radius-sm);
    animation: wire-pulse 1.8s ease-in-out infinite;
}
.wire-skel-avatar { width: 48px; height: 48px; border-radius: 50%; }
.wire-skel-line { height: 10px; margin-top: var(--space-3); }
.wire-skel-line.is-title { height: 14px; width: 70%; margin-top: var(--space-4); }
.wire-skel-line.is-short { width: 45%; }
.wire-skel-tags { display: flex; gap: var(--space-2); margin-top: var(--space-4); }
.wire-skel-tag { height: 22px; width: 64px; border-radius: var(--radius-full); }
.wire-skel-btn { height: 40px; margin-top: var(--space-5); border-radius: var(--radius-full); }

@keyframes wire-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: .55; }
}
@media (prefers-reduced-motion: reduce) {
    .wire-skel { animation: none; }
}

.wire-note {
    margin-top: var(--space-6);
    font-size: .85rem;
    color: var(--color-on-surface-inverse);
    text-align: left;
}

@media (max-width: 900px) {
    .wire-search { grid-template-columns: 1fr; }
    .wire-layout { grid-template-columns: 1fr; }
    .wire-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 620px) {
    .wire-grid { grid-template-columns: 1fr; }
}

/* =============================================================================
   12. NEW PROJECT WIZARD (/dev/new-thing-to-get-done)
   ============================================================================= */

/* A roomier textarea than the survey's, which is tuned for short answers. */
.textarea {
    width: 100%;
    min-height: 110px;
    padding: var(--space-4);
    border: 1px solid #dfe6e0;
    border-radius: var(--radius-md);
    background: #fff;
    color: var(--color-on-surface);
    font-family: var(--font-body);
    font-size: .95rem;
    line-height: 1.55;
    resize: vertical;
    transition: border-color 150ms ease, box-shadow 150ms ease;
}
.textarea::placeholder { color: var(--color-on-surface-inverse); }
.textarea:focus { outline: none; border-color: var(--color-primary); box-shadow: 0 0 0 4px var(--color-primary-dim); }

.project-help {
    font-size: .82rem;
    color: var(--color-on-surface-inverse);
}
/* Used where a group of radios needs a label but there is no single input to
   point a `for` at. */
.project-label {
    font-weight: 600;
    font-size: .9rem;
    color: var(--color-on-surface-variant);
}

/* Radio options as buttons, built the same way as the checkbox options on the
   survey: a bordered chip that fills emerald once it is chosen. The control
   inside stays native and is themed through accent-color. */
.choice-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    /* The chips size to their content. Without this the row stretches them, and the
       tick box drifts to the far left of a chip much wider than its label. */
    justify-content: flex-start;
}
.choice {
    display: inline-flex;
    align-items: center;
    gap: .6rem;
    padding: .7rem .9rem;
    border: 1px solid #e6ebe7;
    border-radius: var(--radius-sm);
    font-size: .93rem;
    color: var(--color-on-surface-variant);
    cursor: pointer;
    transition: background 120ms ease, border-color 120ms ease;
}
.choice:hover { border-color: var(--color-primary); background: var(--color-primary-dim); }
.choice:has(input:checked) { border-color: var(--color-primary); background: var(--color-primary-dim); color: var(--color-on-surface); }

/* The `hidden` attribute alone does nothing here: .choice sets display:
   inline-flex, and an author rule beats the browser's own [hidden] rule. The
   wizard relies on this to swap payment options for a retainer. */
.choice[hidden] { display: none; }

/* The business and affiliate field groups on /dev/join. Same trap, same fix:
   the groups are server-rendered hidden when their track is not ticked, and
   client-join.js toggles them. Stated explicitly so a later `display` on
   .partner-track cannot quietly break the hide. */
.partner-track[hidden] { display: none; }
/* Both control types, because a chip carries a checkbox in the wizard's recurring
   work question and a radio everywhere else. Same box, same accent. */
.choice input[type="radio"],
.choice input[type="checkbox"] {
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    margin: 0;
    accent-color: var(--color-primary-dark);
}

/* ---- The wizard shell ----
   The stepper and the nav stay hidden until the script marks the wrapper ready.
   Without the script every step simply stacks, so nothing is locked behind a
   button that cannot work. */
.project-steps,
.project-nav { display: none; }
.project-wizard[data-wizard-ready] .project-steps { display: flex; }
.project-wizard[data-wizard-ready] .project-nav { display: flex; }

.project-steps {
    flex-wrap: wrap;
    gap: var(--space-2);
    margin: 0 0 var(--space-8);
    padding: 0;
    list-style: none;
}
.project-steps li {
    display: flex;
    align-items: center;
    gap: .5rem;
    font-size: .85rem;
    font-weight: 600;
    color: var(--color-on-surface-inverse);
}
/* A hairline between the steps, not after the last one. */
.project-steps li + li::before {
    content: "";
    width: 24px;
    height: 1px;
    margin-right: var(--space-2);
    background: var(--color-surface-variant);
}
.project-steps li.is-current { color: var(--color-on-surface); }
.project-steps li.is-done { color: var(--color-primary-dark); }
.project-step-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border: 1px solid var(--color-surface-variant);
    border-radius: 50%;
    font-size: .78rem;
    font-weight: 700;
}
.project-steps li.is-current .project-step-num { border-color: var(--color-primary); color: var(--color-primary-dark); }
.project-steps li.is-done .project-step-num { border-color: var(--color-primary); background: var(--color-primary-dim); color: var(--color-primary-dark); }

/* Fieldsets without the browser's default box. */
.project-step {
    margin: 0;
    padding: 0;
    border: 0;
    min-width: 0;
}
.project-step + .project-step { margin-top: var(--space-10); }
.project-step[hidden] { display: none; }
.project-step-title {
    margin: 0 0 var(--space-6);
    padding: 0;
    font-family: var(--font-headline);
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--color-on-surface);
}

/* A heading for a group inside a step, smaller than the step's own title. */
.project-subhead {
    margin: 0 0 var(--space-4);
    font-family: var(--font-headline);
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--color-on-surface);
}

.project-nav {
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
    margin-top: var(--space-10);
    padding-top: var(--space-6);
    border-top: 1px solid var(--color-surface-variant);
}
.project-nav-spacer { flex: 1 1 auto; }
/* The preview marker sits on its own line rather than fighting the buttons. */
.project-nav .account-incomplete { display: inline; margin: 0; }

/* ---- Budget ---- */
.project-range {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-4);
}
.project-range input[type="range"] {
    flex: 1 1 240px;
    min-width: 160px;
    height: 6px;
    accent-color: var(--color-primary);
    cursor: pointer;
}
.project-range output {
    flex: 0 0 auto;
    min-width: 9ch;
    font-family: var(--font-headline);
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--color-on-surface);
}

/* ---- Summary shown on the last step ---- */
.project-summary {
    margin-top: var(--space-8);
    padding: var(--space-5);
    border-left: 3px solid var(--color-primary);
    border-radius: 0 var(--radius-md) var(--radius-md) 0;
    background: var(--color-primary-dim);
    text-align: left;
}
.project-summary[hidden] { display: none; }
.project-summary dl {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: .35rem var(--space-4);
    margin: 0;
}
.project-summary dt {
    font-size: .85rem;
    font-weight: 700;
    color: var(--color-on-surface-variant);
}
.project-summary dd {
    margin: 0;
    font-size: .95rem;
    color: var(--color-on-surface);
}

@media (max-width: 620px) {
    .project-nav .btn { flex: 1 1 100%; }
    .project-nav-spacer { display: none; }
}

/* Shown when a visitor opens their own referral link. */
.refer-self {
    display: flex;
    align-items: flex-start;
    gap: .5rem;
    margin-top: var(--space-4);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    background: rgba(255, 255, 255, 0.14);
    font-size: .85rem;
    color: rgba(255, 255, 255, 0.9);
}

.refer-self[hidden] { display: none; }
.refer-self .material-symbols-outlined { font-size: 18px; flex: 0 0 auto; }

/* A closing paragraph after a bulleted list, for sections that need to state
   what we explicitly do NOT do. */
.legal-after { margin-top: var(--space-4); color: var(--color-on-surface-variant); }

/* -----------------------------------------------------------------------------
   Four ways, phones
   -----------------------------------------------------------------------------
   Last, so it beats the two column rule in the 720px block above.

   Two columns only read well once each card has about 200px of text width,
   which works out at roughly a 560px screen. Below that the descriptions fell
   to three or four words a line and the CTA wrapped to two, so the four ways go
   full width and stack. Every phone gets one column, small tablets get two,
   desktop gets four.
   -------------------------------------------------------------------------- */
@media (max-width: 560px) {
    .ways-grid { grid-template-columns: 1fr; }
}

/* =============================================================================
   13. DROPDOWNS
   =============================================================================
   Ported from the enterramon stylesheet (main.css), recoloured onto the emerald
   tokens. The class names and the structure are theirs, so markup copied out of
   enterramon keeps working.

   Four deliberate departures from the original, listed because they are exactly
   the kind of thing that reads as a bug later:

     1. The chosen item was tinted orange, that brand's accent. It is the emerald
        dim here.
     2. The menu scrolls. Their lists were short; ours are not, and the country
        picker alone is around 250 items.
     3. The menu opens on click, not on hover. Hover-to-open suits a small nav
        menu and is hostile on a form control, where you would unfurl a 250 item
        list just by moving the mouse past it.
     4. The trigger fills its field so it lines up with the inputs around it,
        instead of sizing to its own label.
   ============================================================================= */

.dropdown {
    position: relative;
    display: block;
}

.dropdown-trigger {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-3) var(--space-5);
    background: var(--color-secondary);
    /* The original border was white, which was right on enterramon's coloured
       background and invisible on ours, where every dropdown sits on white. A
       faint emerald edge gives the control a boundary. */
    border: 1px solid rgba(34, 197, 94, .22);
    border-radius: var(--radius-full);
    font: inherit;
    font-weight: 500;
    color: var(--color-on-secondary);
    text-align: left;
    cursor: pointer;
    transition: color 150ms ease, border-color 150ms ease, box-shadow 150ms ease;
}
.dropdown-trigger:hover { color: var(--color-primary); }
.dropdown-trigger:focus-visible {
    outline: none;
    box-shadow: 0 0 0 4px var(--color-primary-dim);
}
.dropdown-trigger .icon {
    margin-left: auto;
    transition: transform 200ms ease;
}
.dropdown.open .dropdown-trigger .icon { transform: rotate(180deg); }

/* The label truncates rather than shoving the chevron out of the box. */
.dropdown-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dropdown-menu {
    /* Fixed, not absolute. Every .has-decal section sets overflow: hidden to clip
       its decals, and an absolutely positioned menu inside one gets clipped at the
       section edge: the tail of the list was simply cut off. A fixed layer is not
       clipped by an ancestor's overflow, so top, left, width and max-height are
       measured from the trigger by dropdown.js instead.

       Caveat for later: an ancestor with transform, filter or will-change creates
       a containing block even for fixed elements, which would bring the clipping
       back. No ancestor of a dropdown does that today. */
    position: fixed;
    overflow-y: auto;
    padding: var(--space-2);
    background: var(--color-surface-elevated);
    /* A white menu on a white card has no edge. The border gives it one, and the
       shadow is heavier than the shared --shadow-lg because the menu floats over
       page content rather than sitting in a layout. */
    border: 1px solid var(--color-surface-variant);
    border-radius: var(--radius-md);
    box-shadow: 0 18px 40px -12px rgba(11, 15, 12, .3), 0 4px 12px -4px rgba(11, 15, 12, .12);
    white-space: normal;
    /* Above the fixed site header, which is z-index 100. The menu is a transient
       overlay on <body> now, so it must clear everything on the page. */
    z-index: 400;

    /* A long list scrolls, and macOS hides overlay scrollbars until you actually
       scroll, so a scrollable menu looked exactly like a clipped one. Styling the
       scrollbar forces it visible, so "there is more below" is never a guess. */
    scrollbar-width: thin;
    scrollbar-color: var(--color-surface-variant) transparent;

    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition: opacity 200ms ease, transform 200ms ease, visibility 200ms;
}
/* visibility, not just opacity: a hidden menu must not be reachable by Tab. */
/* The menu sits on <body>, not inside .dropdown, so it carries its own open
   state. A descendant selector would never match it. */
.dropdown-menu.is-open {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

/* Scrollbar styling is what makes a long list read as scrollable rather than
   chopped. WebKit ignores these if it cannot paint a classic scrollbar, in which
   case the overlay one behaves as usual. */
.dropdown-menu::-webkit-scrollbar { width: 10px; }
.dropdown-menu::-webkit-scrollbar-track { background: transparent; }
.dropdown-menu::-webkit-scrollbar-thumb {
    background: var(--color-surface-variant);
    border: 3px solid var(--color-surface-elevated);
    border-radius: var(--radius-full);
}
.dropdown-menu::-webkit-scrollbar-thumb:hover { background: var(--color-on-surface-inverse); }

.dropdown-item {
    position: relative;
    display: block;
    padding: var(--space-2) var(--space-4);
    border-radius: var(--radius-sm);
    color: var(--color-on-surface);
    cursor: pointer;
    transition: background 150ms ease, color 150ms ease;
}
/* Hover and focus are deliberately NEUTRAL. They used to be green as well, which
   meant a hovered row and the chosen row were the same colour and you could not
   tell which was which. Green now means chosen, and nothing else. */
.dropdown-item:hover,
.dropdown-item:focus-visible {
    outline: none;
    background: var(--color-surface);
    color: var(--color-on-surface);
}
/* The chosen one, and only the chosen one, wears the green. The tick means it
   reads without leaning on colour alone, which matters because the dim green is
   subtle against a white card. */
.dropdown-item.selected {
    padding-right: var(--space-8);
    font-weight: 600;
    color: var(--color-primary-dark);
    background: var(--color-primary-dim);
}
.dropdown-item.selected::after {
    content: "\2713";
    position: absolute;
    top: 50%;
    right: var(--space-4);
    transform: translateY(-50%);
    color: var(--color-primary-dark);
    font-weight: 700;
}

/* Group headings, for a select that uses optgroup. */
.dropdown-group {
    padding: var(--space-2) var(--space-4) var(--space-1);
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--color-on-surface-inverse);
}

/* The native select stays in the form as the real control and only its painting
   is replaced. display:none still submits its value. */
.dropdown-native { display: none; }

/* Set by the wizard when a required dropdown was left empty. */
.dropdown.is-invalid .dropdown-trigger {
    border-color: var(--color-error);
    box-shadow: 0 0 0 4px rgba(176, 37, 0, .12);
}

/* ---- Icon helpers ----
   The component's markup carries `icon icon-sm`. Our glyphs already get their
   font from .material-symbols-outlined, so these only carry sizing; the original
   file also set the font family and a text-shadow trick, which is redundant
   here and would fight the existing rules. */
.icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    user-select: none;
}
.icon-sm { font-size: 1.25rem; }
.icon-lg { font-size: 2rem; }

/* =============================================================================
   14. INFO PANEL
   =============================================================================
   A soft emerald note with a left accent. Used for the budget guidance on the new
   project page: important enough to stand apart from the text around it, not
   loud enough to read as a warning. The dark .callout is the wrong tool for that,
   it shouts.
   ============================================================================= */

.info-panel {
    max-width: 780px;
    margin: 0 auto;
    padding: var(--space-8);
    border-left: 3px solid var(--color-primary);
    border-radius: 0 var(--radius-md) var(--radius-md) 0;
    background: var(--color-primary-dim);
    text-align: left;
}

.info-panel p { color: var(--color-on-surface-variant); }
.info-panel p + p { margin-top: var(--space-4); }

/* The individual points inside the panel. Each is a short heading with a line or
   two under it, so the panel can be scanned rather than read. */
.info-panel-point + .info-panel-point {
    margin-top: var(--space-6);
    padding-top: var(--space-6);
    border-top: 1px solid rgba(34, 197, 94, .22);
}
.info-panel-point h4 {
    margin: 0 0 var(--space-2);
    font-family: var(--font-headline);
    font-size: 1rem;
    font-weight: 700;
    color: var(--color-on-surface);
}

/* =============================================================================
   10b. BUSINESS PRO (/dev/business/pro)
   =============================================================================
   The upgrade page. Sits just after the client-area block because it shares that
   area's hero, and before nothing else depends on it.

   The comparison table has its own scroll container with min-width: 0, for the
   same reason every other table in this codebase does: a three-column table with
   long feature labels takes its min-content width otherwise, and drags the page
   wide instead of scrolling inside its own box.
   ============================================================================= */

.pro-body {
    padding: var(--space-12) 0 var(--space-20);
    background: var(--color-surface);
}

.pro-notice {
    margin-bottom: var(--space-6);
    padding: var(--space-4) var(--space-5);
    border-radius: var(--radius-md);
    border: 1px solid var(--color-surface-variant);
    background: var(--color-surface-elevated);
}

.pro-notice.is-ok { border-color: var(--color-primary); color: var(--color-primary-darker); }
.pro-notice.is-bad { border-color: #b02500; color: #b02500; }

/* ---- The price block ---- */

.pro-price {
    padding: var(--space-8);
    border-radius: var(--radius-md);
    background: var(--color-ink);
    color: #fff;
    text-align: center;
}

.pro-price-main {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: .5rem;
    flex-wrap: wrap;
}

.pro-price-amount {
    font-family: var(--font-headline);
    font-size: clamp(2.75rem, 8vw, 4.5rem);
    line-height: 1;
    color: var(--color-primary-light);
}

.pro-price-cadence {
    font-size: 1rem;
    color: rgba(255, 255, 255, .65);
}

.pro-price-tagline {
    max-width: 34rem;
    margin: var(--space-4) auto 0;
    color: rgba(255, 255, 255, .78);
    line-height: 1.7;
}

.pro-price form { margin-top: var(--space-8); }

.pro-price-note {
    max-width: 38rem;
    margin: var(--space-4) auto 0;
    font-size: .85rem;
    line-height: 1.6;
    color: rgba(255, 255, 255, .6);
}

/* Shown in the hero when the account is already on PRO. */
.pro-current {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    margin-top: var(--space-4);
    padding: .5rem 1rem;
    border-radius: var(--radius-full);
    background: rgba(134, 239, 172, .16);
    color: var(--color-primary-light);
    font-weight: 600;
}

.pro-current .material-symbols-outlined { font-size: 1.15rem; }

/* ---- Sections ---- */

.pro-compare,
.pro-limits { margin-top: var(--space-16); }

.pro-h2 {
    font-family: var(--font-headline);
    font-size: clamp(1.5rem, 3.5vw, 2rem);
    color: var(--color-on-surface);
}

.pro-lede {
    max-width: 40rem;
    margin-top: var(--space-3);
    color: var(--color-on-surface-variant);
    line-height: 1.7;
}

/* ---- The comparison table ---- */

.pro-table-wrap {
    margin-top: var(--space-6);
    width: 100%;
    max-width: 100%;
    min-width: 0;
    overflow-x: auto;
    border: 1px solid var(--color-surface-variant);
    border-radius: var(--radius-md);
    background: var(--color-surface-elevated);
}

.pro-table {
    width: 100%;
    min-width: 40rem;
    border-collapse: collapse;
    font-size: .92rem;
}

.pro-table th,
.pro-table td {
    padding: var(--space-4) var(--space-5);
    text-align: left;
    border-bottom: 1px solid var(--color-surface-variant);
    vertical-align: top;
}

.pro-table thead th {
    position: sticky;
    top: 0;
    background: var(--color-surface-elevated);
    font-family: var(--font-headline);
    font-size: .95rem;
    border-bottom: 2px solid var(--color-surface-variant);
}

.pro-table tbody tr:last-child th,
.pro-table tbody tr:last-child td { border-bottom: none; }

/* The feature name is a row header, so it reads as a label rather than data. */
.pro-table tbody th {
    font-weight: 600;
    color: var(--color-on-surface);
}

.pro-table td { color: var(--color-on-surface-variant); }

.pro-table .pro-col-pro {
    background: rgba(34, 197, 94, .06);
    color: var(--color-on-surface);
    font-weight: 600;
}

.pro-table thead .pro-col-pro { color: var(--color-primary-darker); }

/* "From launch" — the mark that keeps the page honest about what is not built. */
.pro-soon {
    display: inline-block;
    margin-left: .5rem;
    padding: .15rem .5rem;
    border-radius: var(--radius-full);
    background: rgba(34, 197, 94, .12);
    color: var(--color-primary-darker);
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    vertical-align: middle;
    white-space: nowrap;
}

.pro-note {
    display: block;
    margin-top: .35rem;
    font-size: .78rem;
    font-weight: 400;
    line-height: 1.5;
    color: var(--color-on-surface-variant);
}

.pro-disclaimer {
    margin-top: var(--space-5);
    font-size: .82rem;
    line-height: 1.7;
    color: var(--color-on-surface-variant);
}

/* ---- Feature rows: icon, label, caveat ---- */

.pro-feature {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
    min-width: 0;
}

/* The glyph is nested in its own span on purpose: material-symbols-outlined on
   the same element as a layout class lands the glyph top-left. */
.pro-feature-icon {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--radius-full);
    background: rgba(34, 197, 94, .12);
    color: var(--color-primary-darker);
}

.pro-feature-icon .material-symbols-outlined { font-size: 1.15rem; }

.pro-feature-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.pro-feature-label {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
}

/* The caveat already brings its own top margin; cancel the doubled gap. */
.pro-feature-text .pro-note { margin-top: .2rem; }

/* ---- What every plan gets ---- */

.pro-standard { margin-top: var(--space-16); }

.pro-standard-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
    gap: var(--space-4);
    margin-top: var(--space-6);
}

.pro-standard-item {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
    padding: var(--space-5);
    border: 1px solid var(--color-surface-variant);
    border-radius: var(--radius-md);
    background: var(--color-surface-elevated);
    min-width: 0;
}

/* ---- The numbers ---- */

.pro-limit-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
    gap: var(--space-4);
    margin-top: var(--space-6);
}

.pro-limit {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-5);
    border: 1px solid var(--color-surface-variant);
    border-radius: var(--radius-md);
    background: var(--color-surface-elevated);
    min-width: 0;
}

.pro-limit-label {
    font-size: .8rem;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--color-on-surface-variant);
}

.pro-limit-values {
    display: flex;
    align-items: center;
    gap: .75rem;
    font-family: var(--font-headline);
}

.pro-limit-free { font-size: 1.5rem; color: var(--color-on-surface-variant); }
.pro-limit-pro  { font-size: 1.75rem; color: var(--color-primary-darker); }
.pro-limit-values .material-symbols-outlined { font-size: 1.1rem; color: var(--color-on-surface-variant); }

.pro-foot {
    margin-top: var(--space-16);
    display: flex;
    justify-content: center;
}

@media (max-width: 720px) {
    .pro-body { padding: var(--space-10) 0 var(--space-16); }
    .pro-price { padding: var(--space-6) var(--space-4); }
    .pro-compare, .pro-limits { margin-top: var(--space-12); }
    .pro-table th, .pro-table td { padding: var(--space-3) var(--space-4); }
}

/* The plan panel on the business track page. Same shell as the other track
   panels, with a badge that goes green on PRO. */
.track-plan .track-panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
}

.track-plan-badge {
    padding: .25rem .75rem;
    border-radius: var(--radius-full);
    background: var(--color-surface-variant);
    color: var(--color-on-surface-variant);
    font-size: .75rem;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    white-space: nowrap;
}

.track-plan-badge.is-pro {
    background: rgba(34, 197, 94, .16);
    color: var(--color-primary-darker);
}

/* =============================================================================
   OPENING HOURS TABLE  (/businesses/{slug})
   =============================================================================
   THE ONLY NEW CSS THIS PAGE NEEDS, and it is new because the theme has no table
   styling anywhere: every other page uses .compare, .stats-band or .card grids,
   none of which is a seven-row label/value table.

   It uses only existing tokens, so it changes with the theme rather than beside
   it. Nothing here restates a .card, a .grid or a .btn.
   ============================================================================= */

.hours-table {
    width: 100%;
    margin-top: var(--space-4);
    border-collapse: collapse;
    font-size: .95rem;
}

.hours-table th,
.hours-table td {
    padding: var(--space-2) 0;
    text-align: left;
    border-bottom: 1px solid #eef1ee;
    vertical-align: top;
}

.hours-table th { font-weight: 600; color: var(--color-on-surface); }
.hours-table td { color: var(--color-on-surface-variant); }
.hours-table tr:last-child th,
.hours-table tr:last-child td { border-bottom: none; }

/* Today, marked so it is found without reading every row. */
.hours-table tr.is-today th,
.hours-table tr.is-today td {
    color: var(--color-primary-dark);
    font-weight: 700;
}

/* =============================================================================
   CAPABILITY BOARD  (the builder's "Everything a business website needs")
   =============================================================================
   Seven groups and fifty-six items, all visible at once. No buttons, no bullet
   markers. The chips wrap under their group heading instead of scrolling; the
   only motion is the platform's own scroll-reveal entrance, which cannot jank a
   moving list because nothing here moves.

   Contrast: `--color-on-surface-variant` on `--color-surface-elevated` — the
   `.legal-list` pairing, 6.53:1. The chips are the bigger ones the owner asked
   for (font and padding up from the first pass).
   ============================================================================= */

.chip-board { display: flex; flex-direction: column; }

/* A group is a heading over a wrapping row of chips, separated from its
   neighbours by a hairline so seven groups read as seven blocks rather than one
   long pile. */
.chip-group {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-4);
    padding: var(--space-6) 0;
    border-top: 1px solid var(--color-surface-variant);
}
.chip-group:first-child { border-top: none; padding-top: 0; }
.chip-group:last-child { padding-bottom: 0; }

.chip-group-head { display: flex; align-items: center; gap: var(--space-3); }

.chip-group-icon {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--radius-full);
    background: var(--color-primary-dim);
    color: var(--color-primary-dark);
}
.chip-group-icon .material-symbols-outlined { font-size: 1.3rem; line-height: 1; }

/* The theme leaves `h1`–`h5` without a SIZE on purpose, so the heading carries
   its own — same reason the band uses `.h3`. */
.chip-group-title {
    font-family: var(--font-headline);
    font-weight: 600;
    font-size: 1.05rem;
    letter-spacing: -.01em;
    color: var(--color-on-surface);
    margin: 0;
}

.chip-group-body {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
}

.chip {
    display: inline-flex;
    align-items: center;
    padding: .7rem 1.3rem;
    border: 1px solid var(--color-surface-variant);
    border-radius: var(--radius-full);
    background: var(--color-surface-elevated);
    color: var(--color-on-surface-variant);
    font-size: 1.05rem;
    font-weight: 500;
    line-height: 1.25;
    white-space: nowrap;
    box-shadow: 0 1px 2px rgba(16, 24, 20, .05);
    transition: transform .3s cubic-bezier(.34, 1.56, .64, 1), border-color .2s ease, color .2s ease, box-shadow .2s ease;
}
/* The lift is safe again: a chip no longer has a translating parent, so its own
   transform is the only transform in play.

   THE HOVER IS SCOPED TO ENABLED CHIPS, which is what "no hover css" means for a
   disabled one. Scoping the SELECTOR is better than writing a second rule that
   undoes the first: an override has to restate all four properties, and the day
   somebody adds a fifth to the hover it silently comes back on disabled chips. */
.chip:not([aria-disabled="true"]):hover {
    color: var(--color-primary-darker);
    border-color: var(--color-primary);
    transform: translateY(-3px);
    box-shadow: 0 12px 24px -14px rgba(34, 197, 94, .5);
}

/* An unavailable chip is DIMMED, at the owner's stated figure of 50%. The state
   rides on `aria-disabled`, which the markup already sets for the screen reader,
   so the appearance and the announced state cannot drift apart — there is no
   separate class that could be left behind. The whole chip dims, crown and
   "Coming soon" pill included, because the element is what is unavailable. */
.chip[aria-disabled="true"] { opacity: .5; }

/* An unavailable ITEM IN A PRICE CARD'S CHECK LIST is dimmed at the same 50%, and
   for the same reason. The owner, on the Business Pro website list: **"you didn't
   change the opacity of the ones that are disabled"** — the list showed an unbuilt
   feature looking exactly like a built one, while the chip board above it (and the
   builder's $25 card beside it) greyed it.

   SCOPED TO `.price-card li`, NOT TO EVERY `[aria-disabled]`. A bare attribute
   selector would reach controls that already have their own disabled treatment —
   `.account-danger .btn:disabled` and `.wire-check input:disabled` both use `.55`
   and add `cursor: not-allowed` — and quietly change them. This rule only ever
   touches the two Pro lists, which are the only things that set the attribute on
   an `<li>`.

   THE CONTRAST COST IS REAL AND IS THE OWNER'S CALL. `--color-on-surface-variant`
   on `--color-surface-elevated` is 6.53:1; at 50% the item lands near 3:1, below
   AA for body text. That is deliberate — greyed means less prominent, and the
   alternative reading is that "Coming soon" is unavailable and must not look
   available. The chip does exactly this already. */
.price-card li[aria-disabled="true"] { opacity: .5; }
