/**
 * ChordSpheres — landing design system
 *
 * The `_design-lab` concepts as real, reusable app CSS. The lab stylesheet
 * was standalone: it redefined the palette and shipped a global `*` reset so
 * the exploration wasn't shaped by app.css. Neither is wanted here, so this
 * port drops both and maps every lab token onto the `--cs-*` token that
 * already holds the same value in app.css. That matters for one concrete
 * reason: the marketing layout honours the `cs-theme` light/dark toggle, and
 * a parallel hardcoded dark palette would have ignored it.
 *
 * Class names carry the `cs-` prefix per the project rule. Four lab names
 * were already taken in app.css (`hero`, `grid`, `card`, `btn`), so those
 * became `cs-stage`, `cs-band`, `cs-tile`, and — for buttons — app.css's own
 * `.cs-btn` plus a pill modifier, rather than a second button system.
 *
 * Ground modifiers (`--surface`, `--raised`) are standalone rather than tied
 * to `.cs-act`: the lab put `act--surface` on `.grid` elements too, which
 * only worked because the rule was a bare background.
 */

:root {
    /* Only the tokens app.css doesn't already carry. */
    --cs-sphere-lit: #00C6FF;      /* the lit edge of the digital half */
    --cs-text-dim:   #c0c0c4;      /* brighter than --cs-text-secondary; for lede-size body copy */
    --cs-ease-out:   cubic-bezier(0.23, 1, 0.32, 1);
    --cs-gutter:     clamp(1.25rem, 5vw, 6rem);
    --cs-stack:      clamp(5rem, 14vh, 11rem);
}

[data-theme="light"] {
    --cs-sphere-lit: #005FCC;
    --cs-text-dim:   #4A525C;
}

/* ==========================================================================
   Type. Tracking is size-specific: display needs negative, small caps need
   positive. One fixed letter-spacing is wrong at one end.
   ========================================================================== */

.cs-display {
    font-size: clamp(2.1rem, 8vw, 7rem);
    font-weight: 700; line-height: .99; letter-spacing: -.04em;
    text-wrap: balance; margin: 0;
}
.cs-headline {
    font-size: clamp(1.9rem, 5vw, 4.2rem);
    font-weight: 660; line-height: 1.06; letter-spacing: -.03em;
    text-wrap: balance; margin: 0;
}
.cs-eyebrow {
    font-size: .74rem; font-weight: 620; letter-spacing: .14em;
    text-transform: uppercase; color: var(--cs-sphere-lit); margin: 0;
    display: block;
}
.cs-lede {
    font-size: clamp(1.02rem, 1.45vw, 1.32rem); line-height: 1.55;
    letter-spacing: -.005em; color: var(--cs-text-dim);
    max-width: 46ch; text-wrap: pretty; margin: 0;
}
.cs-lede--centre { text-align: center; margin-inline: auto; }
.cs-lede--faint  { color: var(--cs-text-tertiary); font-size: .92rem; }

/* The craft half of the argument is orange wherever it appears. */
.cs-eyebrow--craft { color: var(--cs-accent); }
/* The half-sentence the hero headline turns on. */
.cs-lit { color: var(--cs-sphere-lit); font-style: normal; }

/* ==========================================================================
   Grounds — shared by every section type
   ========================================================================== */

.cs-ground--surface { background: var(--cs-surface); }
.cs-ground--raised  { background: var(--cs-surface-raised); }

/* ==========================================================================
   Buttons — app.css's .cs-btn, given the marketing pill shape
   ========================================================================== */

.cs-btn--pill {
    border-radius: var(--cs-radius-full);
    padding: .85rem 1.9rem;
    font-size: .95rem;
    font-weight: 560;
}
.cs-btn--pill.cs-btn--ghost {
    background: transparent;
    color: var(--cs-text);
    box-shadow: inset 0 0 0 1px var(--cs-border-strong);
}
/* Over a photograph the ghost outline has to hold against the image, not the
   page background, so it stays light in both themes. */
.cs-on-media .cs-btn--ghost {
    color: #fff;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .38);
}

/* ==========================================================================
   Stage — the full-bleed opening. Copy sits at the bottom, over the image.
   ========================================================================== */

.cs-stage {
    position: relative; min-height: 100svh;
    display: grid; align-items: end;
    /* Top padding clears the fixed nav. The copy is bottom-aligned, so a
       block tall enough to fill the stage grows upwards — without this the
       first line (the eyebrow) slides under the bar and is clipped by the
       overflow rule below. */
    padding: calc(var(--cs-nav-height, 60px) + 1.5rem) var(--cs-gutter) clamp(3rem, 9vh, 6rem);
    overflow: hidden; isolation: isolate;
}
.cs-stage__media {
    position: absolute; inset: 0; z-index: -2;
    width: 100%; height: 100%; object-fit: cover; opacity: .5;
}
.cs-stage::after {
    content: ""; position: absolute; inset: 0; z-index: -1;
    background: linear-gradient(180deg,
        rgba(13,13,15,.50) 0%, rgba(13,13,15,.20) 35%, rgba(13,13,15,.95) 100%);
}
.cs-stage__inner { display: grid; gap: 1.5rem; max-width: min(100%, 36rem); }
/* Measure on the HEADLINE — 1ch here is a character of the display font,
   which is what "about fifteen characters wide" actually means. */
.cs-stage .cs-display { max-width: 15ch; }
.cs-stage__cta { display: flex; gap: .75rem; flex-wrap: wrap; margin-top: .5rem; }

/* Anything painted over a photograph keeps light text in both themes — the
   overlay under it is dark either way.

   The ground has to be explicit. The media sits at reduced opacity, so it
   composites against whatever is behind it; with no background of its own the
   section inherits the page's, and in light mode the image washes out to grey.
   The eyebrow has to be pinned for the same reason — left on the theme token
   it turns dark blue over a dark image, which measured 1.13:1 against it. */
.cs-on-media { background: #0d0d0f; }
.cs-on-media, .cs-on-media .cs-display, .cs-on-media .cs-headline { color: #fff; }
.cs-on-media .cs-lede { color: rgba(255,255,255,.86); }
.cs-on-media .cs-lede--faint { color: rgba(255,255,255,.62); }
.cs-on-media .cs-eyebrow, .cs-on-media .cs-lit { color: #00C6FF; }

/* ==========================================================================
   Page head — how an interior page opens. The lab's courses and store
   concepts both lead with the organising idea at display size rather than
   with a search box and a row of controls.
   ========================================================================== */

.cs-pagehead {
    padding: clamp(4rem, 10vh, 7rem) var(--cs-gutter) clamp(2rem, 5vh, 3rem);
    max-width: 68rem; margin: 0 auto;
    display: grid; gap: 1.25rem; justify-items: start;
}
.cs-pagehead .cs-display { max-width: 16ch; }

/* ==========================================================================
   Act — alternating text/media panels
   ========================================================================== */

.cs-act {
    display: grid; gap: clamp(2rem, 5vw, 4.5rem); grid-template-columns: 1fr;
    align-items: center; padding: var(--cs-stack) var(--cs-gutter);
}
@media (min-width: 900px) {
    .cs-act { grid-template-columns: 1fr 1fr; }
    .cs-act--flip .cs-act__media { order: -1; }
}
.cs-act__text { display: grid; gap: 1.25rem; justify-items: start; }
.cs-act__text > p { margin: 0; }
.cs-act__media img { width: 100%; border-radius: 20px; aspect-ratio: 4/3; object-fit: cover; }

/* ==========================================================================
   Statement — one sentence, full width, over an optional image
   ========================================================================== */

.cs-statement {
    position: relative; min-height: 80svh;
    display: grid; place-items: center; text-align: center;
    padding: var(--cs-stack) var(--cs-gutter);
    overflow: hidden; isolation: isolate;
}
.cs-statement__bg {
    position: absolute; inset: 0; z-index: -2;
    width: 100%; height: 100%; object-fit: cover; opacity: .35;
}
.cs-statement:has(.cs-statement__bg)::after {
    content: ""; position: absolute; inset: 0; z-index: -1; background: rgba(13,13,15,.55);
}
.cs-statement__inner { display: grid; gap: 1.6rem; justify-items: center; max-width: min(100%, 48rem); }
.cs-statement .cs-display { max-width: 18ch; margin-inline: auto; }
.cs-statement .cs-lede { max-width: 52ch; }
/* The pivot sentence is long — it reads as a statement, not a banner headline. */
.cs-statement--quiet { min-height: 64svh; }
.cs-statement--quiet .cs-display { font-size: clamp(1.8rem, 4.6vw, 3.6rem); }

/* ==========================================================================
   Split — the two halves. ChordSpheres' central idea is a pair, so the
   layout is literally a pair.
   ========================================================================== */

.cs-split { display: grid; gap: 1px; background: var(--cs-border-strong); padding: 0; }
@media (min-width: 820px) { .cs-split { grid-template-columns: 1fr 1fr; } }
.cs-split__half {
    background: var(--cs-bg);
    padding: clamp(2.5rem, 6vw, 5rem) var(--cs-gutter);
    display: grid; gap: 1rem; align-content: center;
}
.cs-split__half h3 {
    font-size: clamp(1.4rem, 2.6vw, 2.1rem); font-weight: 660;
    letter-spacing: -.022em; margin: 0;
}

/* ==========================================================================
   Band — a centred head over a row of tiles
   ========================================================================== */

.cs-band { padding: var(--cs-stack) var(--cs-gutter); }
.cs-band--tight-bottom { padding-bottom: 0; }
.cs-band__head {
    display: grid; gap: 1rem; max-width: 44rem;
    margin: 0 auto clamp(3rem, 7vh, 4.5rem);
    text-align: center; justify-items: center;
}
.cs-band__items {
    display: grid; gap: 1.25rem; max-width: 78rem; margin: 0 auto;
    grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
}
.cs-band__items--pair { max-width: 60rem; }
.cs-band__note {
    max-width: 60rem; margin: 2.5rem auto 0; text-align: center;
    color: var(--cs-text-tertiary); font-size: .94rem; line-height: 1.6;
}
.cs-band__note strong { color: var(--cs-text); }

.cs-tile {
    background: var(--cs-surface); border: 1px solid var(--cs-border); border-radius: 18px;
    padding: clamp(1.5rem, 3vw, 2.1rem); display: grid; gap: .55rem; align-content: start;
    transition: transform 240ms var(--cs-ease-out), border-color 240ms var(--cs-ease-out);
}
@media (hover: hover) and (pointer: fine) {
    .cs-tile:hover { transform: translateY(-4px); border-color: var(--cs-border-strong); }
}
.cs-tile h3 { font-size: 1.15rem; font-weight: 640; letter-spacing: -.018em; margin: 0; }
.cs-tile p { font-size: .94rem; line-height: 1.55; color: var(--cs-text-dim); margin: 0; }
.cs-tile__num {
    font-size: .72rem; letter-spacing: .14em; text-transform: uppercase;
    color: var(--cs-sphere-lit); margin: 0;
}

/* ==========================================================================
   Scroll reveal. Fixed distance, not a percentage: the `entry` phase is
   measured against the element's own height, so a percentage makes tall
   blocks reveal more slowly than short ones — backwards.
   ========================================================================== */

@keyframes cs-rise { from { opacity: 0; transform: translateY(26px); } to { opacity: 1; transform: none; } }

@supports (animation-timeline: view()) {
    .cs-act__text, .cs-act__media, .cs-band__head, .cs-tile,
    .cs-statement__inner, .cs-split__half {
        animation: cs-rise linear both;
        animation-timeline: view();
        animation-range: entry 0% entry 250px;
    }
}

/* app.css's global reduced-motion rule clamps animation-duration, which a
   view-timeline animation ignores. These have to be switched off by name. */
@media (prefers-reduced-motion: reduce) {
    .cs-act__text, .cs-act__media, .cs-band__head, .cs-tile,
    .cs-statement__inner, .cs-split__half {
        animation: none !important; opacity: 1 !important; transform: none !important;
    }
    .cs-tile:hover { transform: none; }
}
