/* ============================================================================
   PIA SYSTEM — LANDING
   REQUIRES styles/global.css.

   COLOUR: nothing is defined here. Every colour is a variable from
   global.css, so the light/dark toggle works with no per-page work and there
   is not a single raw hex value in this file. The palette is exactly:
   surface tones, text tones, green accent, and red/amber for semantics.

   SIZING: no fixed layout dimensions. Sections size to their content, type
   scales with clamp(), and the only fixed values are control heights and
   locked aspect-ratios — both of which exist to PREVENT layout shift.
   ==========================================================================*/

/* --------------------------------------------------- 1. PAGE RHYTHM ---- */
:root {
    /* Spacing rhythm for this page, derived from the global scale. */
    --band: clamp(var(--sp-9), 9vh, 7rem);
    --gutter: clamp(var(--sp-5), 5vw, var(--sp-9));

    --font: 'Plus Jakarta Sans', 'Jakarta Metrics Fallback', 'Inter',
        -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

/* Metrics-matched fallback so the webfont swap costs no layout shift. */
@font-face {
    font-family: 'Jakarta Metrics Fallback';
    src: local('Arial');
    size-adjust: 104%;
    ascent-override: 96%;
    descent-override: 23%;
    line-gap-override: 0%;
}

body { background: var(--bg-body); color: var(--text); }

/* Theme changes are colour-only, so switching can never shift the layout. */
body,
.site-nav::before,
.panel, .media, .btn, .step, .theme-toggle {
    transition: background-color var(--t-layout), color var(--t-layout),
                box-shadow var(--t-layout);
}

@media (prefers-reduced-motion: reduce) {
    .js [data-reveal] { opacity: 1 !important; transform: none !important; }
    * { transition-duration: 1ms !important; animation-duration: 1ms !important; }
}

/* ------------------------------------------------------- 2. CONTAINERS - */
.site { position: relative; }

/* The single horizontal rhythm. Anything that also wears .shell must set
   vertical padding with LONGHAND, or its shorthand will silently reset this
   gutter to zero. */
.shell {
    width: 100%;
    max-width: 72rem;
    margin-inline: auto;
    padding-inline: var(--gutter);
}

.section { padding-block: var(--band); }
.section-tight { padding-block-end: var(--band); }

/* ------------------------------------------------------------ 3. NAV --- */
.site-nav {
    position: sticky;
    top: 0;
    z-index: var(--z-sticky);
    min-height: var(--topbar-h);
    display: flex;
    align-items: center;
}

/* Opacity-only, so becoming "stuck" mid-scroll stays on the compositor. */
.site-nav::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: var(--bg-body);
    box-shadow: var(--shadow-under);
    opacity: 0;
    transition: opacity var(--t-layout);
}

.site-nav.is-stuck::before { opacity: 1; }

.site-nav-inner {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-3);
    width: 100%;
}

.brand {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-3);
    flex: 0 0 auto;
    border-radius: var(--r-md);
}

.brand:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.brand-mark {
    width: var(--icon-btn);
    height: var(--icon-btn);
    flex: 0 0 var(--icon-btn);
    border-radius: var(--r-md);
    background: var(--accent);
    color: var(--on-accent);
    display: grid;
    place-items: center;
    font-size: 0.8125rem;
    font-weight: 800;
}

.brand-name { font-size: 0.9375rem; font-weight: 700; letter-spacing: -0.01em; }

.nav-links {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-2);
    margin-inline-start: auto;
}

.nav-link {
    display: inline-flex;
    align-items: center;
    height: var(--control-h);
    padding-inline: var(--sp-3);
    border-radius: var(--r-md);
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-muted);
    transition: background-color var(--t-base), color var(--t-base);
}

.nav-link:hover { background: var(--bg-chip); color: var(--text); }
.nav-link:active { background: var(--bg-chip-hover); }
.nav-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---- 3.1 Theme toggle: fixed box, so flipping themes changes only colour */
.theme-toggle {
    width: var(--icon-btn);
    height: var(--icon-btn);
    flex: 0 0 var(--icon-btn);
    display: grid;
    place-items: center;
    border-radius: var(--r-md);
    background: var(--bg-chip);
    color: var(--text-muted);
    transition: background-color var(--t-base), color var(--t-base);
}

.theme-toggle:hover { background: var(--bg-chip-hover); color: var(--text); }
.theme-toggle:active { background: var(--bg-chip-hover); }
.theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.theme-toggle .icon-moon { display: none; }
:root[data-theme="light"] .theme-toggle .icon-sun { display: none; }
:root[data-theme="light"] .theme-toggle .icon-moon { display: block; }

/* ------------------------------------------------------------ 4. HERO -- */
/* STAGE 1 — "Meet your buddy". A full-viewport panel:

       .hero-info     greeting, description, switcher + auth  (LEFT)
       .hero-visual   radial glow + <model-viewer>            (RIGHT)

   Height comes from the viewport, with the figure's locked aspect-ratio as
   the floor — so the box is correct at first paint, before the model or even
   its script exists. */
.hero {
    /* svh, not vh: on mobile browsers vh is the height with the URL bar
       HIDDEN, so a 100vh hero is taller than the visible viewport on load
       and the content sits partly under the chrome. svh is the small
       (chrome-visible) height, which is the one that always fits. The vh
       line is the fallback for engines without svh. */
    min-height: calc(100vh - var(--topbar-h));
    min-height: calc(100svh - var(--topbar-h));

    display: flex;
    flex-direction: column;
    justify-content: center;
    position: relative;
    padding-block: clamp(var(--sp-6), 5vh, var(--sp-9));
}

/* The scroll cue. Absolutely positioned, so it adds no height and cannot
   push the split off-centre or shift anything. */
.hero-scroll-cue {
    position: absolute;
    inset-block-end: var(--sp-5);
    inset-inline-start: 50%;
    translate: -50% 0;
    /* Hidden by default. The stacked mobile column runs the full height of
       the hero, so a centred cue lands ON the Sign up button — measured at a
       23x38px overlap. Only the two-column layout has slack for it. */
    display: none;
    place-items: center;
    width: var(--control-h);
    height: var(--control-h);
    border-radius: var(--r-pill);
    color: var(--text-faint);
    pointer-events: none;
    animation: heroCue 2.6s var(--ease) infinite;
}

@keyframes heroCue {
    0%, 100% { transform: translateY(0); opacity: 0.5; }
    50%      { transform: translateY(0.375rem); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .hero-scroll-cue { animation: none; opacity: 0.6; }
}

/* Shown only where the split is side-by-side AND the viewport is tall enough
   to leave clear space beneath the content. */
@media (min-width: 60rem) and (min-height: 40rem) {
    .hero-scroll-cue { display: grid; }
}

/* ---- 4.1 The greeting ----
   This is the page's <h1>: the first thing said, above the fold. The massive
   "Welcome to PIA" in stage 2 is an <h2> — one h1 per document — but it
   carries the display styling regardless of its level. */
.hero-greeting {
    margin: 0;
    font-family: var(--font-display);
    font-size: clamp(1.75rem, 4.2vw, 3rem);
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.02em;
    color: var(--text);
    text-wrap: balance;
}

.hero-greeting-accent {
    display: block;
    color: var(--accent);
}

/* ---- 4.2 The split ----
   Mobile-first: one column. The 50/50 grid is opt-in at the wide breakpoint,
   so narrow screens never pay for a rule they have to undo. */
.hero-split {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(var(--sp-6), 5vh, var(--sp-8));
    align-items: center;
}

@media (min-width: 60rem) {
    .hero-split {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: clamp(var(--sp-7), 4vw, var(--sp-9));
    }
}

/* ---- 4.3 Left column: character info + auth ----
   Deliberately NO surface — no background, no border, no shadow. The text
   and the buttons sit straight on the page. */
.hero-info {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-4);
    text-align: center;
    /* On mobile the 3D goes above this block: seeing the character first,
       then reading about it, is the natural order for a chooser. */
    order: 1;
}

@media (min-width: 60rem) {
    .hero-info { align-items: flex-start; text-align: start; }
}

.hero-eyebrow {
    margin: 0;
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--accent);
}

/* Reserved single line: the name changes as characters are switched, and a
   fixed min-height keeps the column from resizing when it does. */
.hero-character-name {
    margin: 0;
    min-height: 1.15em;
    font-family: var(--font-display);
    font-size: clamp(1.75rem, 4vw, 2.75rem);
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.02em;
    color: var(--text);
}

/* Three lines are reserved, so swapping descriptions of similar length does
   not move the buttons underneath. */
.hero-character-desc {
    margin: 0;
    max-width: 42ch;
    min-height: calc(3 * 1.65em);
    font-size: clamp(1rem, 1.5vw, 1.0625rem);
    line-height: 1.65;
    color: var(--text-muted);
}

/* Switcher and auth buttons share one row, wrapping rather than crushing. */
.hero-actions {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: var(--sp-4);
    margin-block-start: var(--sp-2);
}

@media (min-width: 60rem) {
    .hero-actions { justify-content: flex-start; }
}

.hero-switcher {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    flex: 0 0 auto;
}

.hero-auth {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-3);
    flex: 0 0 auto;
}

.switch-arrow {
    width: var(--control-h-lg);
    height: var(--control-h-lg);
    flex: 0 0 var(--control-h-lg);
    display: grid;
    place-items: center;
    border-radius: var(--r-pill);
    background: var(--bg-chip);
    color: var(--text);
    transition: background-color var(--t-base), color var(--t-base);
}

.switch-arrow:hover:not(:disabled) { background: var(--bg-chip-hover); }
.switch-arrow:active:not(:disabled) { background: var(--bg-chip-hover); box-shadow: inset 0 2px 4px color-mix(in srgb, var(--bg-dark) 30%, transparent); }
.switch-arrow:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.switch-arrow:disabled { opacity: 0.4; cursor: not-allowed; }

/* Dots are real buttons, not divs — each selects a character. */
.switch-dots { display: flex; align-items: center; gap: var(--sp-2); }

.switch-dot {
    width: 0.625rem;
    height: 0.625rem;
    flex: 0 0 0.625rem;
    padding: 0;
    border-radius: var(--r-pill);
    background: var(--track);
    transition: background-color var(--t-base), box-shadow var(--t-base);
}

.switch-dot:hover { background: var(--track-hover); }
.switch-dot:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.switch-dot[aria-current="true"] { background: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }

/* ---- 4.4 Right column: the 3D element ----
   The column is only a positioning context for two layers: the glow behind,
   the figure in front. It has no surface of its own. */
.hero-visual {
    position: relative;
    isolation: isolate;              /* a self-contained stacking context */
    display: grid;
    place-items: center;
    width: 100%;
    order: 0;                        /* above the info on mobile */

    /* Single source of truth for the centrepiece. The figure uses it and the
       glow is derived from it, so the two can never drift apart at any
       breakpoint. Mobile-first: the smaller value is the default, because a
       3:4 box at full column width swallows a phone screen whole. */
    --figure-w: min(72%, 17rem);
}

@media (min-width: 60rem) {
    .hero-visual {
        order: 1;                    /* right-hand column on desktop */
        --figure-w: min(88%, 26rem);
    }
}

/* A soft pool of primary light, and nothing else — no box, no border, no
   card. color-mix() derives every stop from --color-primary, so the glow
   follows the palette token instead of repeating a literal colour. The flat
   fallback on the line above covers engines without color-mix(). */
.hero-glow {
    position: absolute;
    z-index: 0;
    inset-block-start: 50%;
    inset-inline-start: 50%;
    translate: -50% -50%;
    width: calc(var(--figure-w) * 1.3);
    aspect-ratio: 1;
    border-radius: var(--r-pill);
    background: var(--accent-soft);
    background: radial-gradient(circle at 50% 45%,
        color-mix(in srgb, var(--color-primary) 40%, transparent) 0%,
        color-mix(in srgb, var(--color-primary) 20%, transparent) 38%,
        color-mix(in srgb, var(--color-primary) 6%, transparent) 62%,
        transparent 78%);
    filter: blur(8px);
    pointer-events: none;
}

/* THE CLS CONTRACT: fluid width, locked ratio. No background and no
   overflow clipping — the model is meant to sit on the glow, not in a box. */
.hero-figure {
    position: relative;
    z-index: 1;
    width: var(--figure-w);
    aspect-ratio: 3 / 4;
    margin: 0;
    display: grid;
    place-items: center;
}

.hero-figure > canvas,
.hero-figure > img,
.hero-figure > video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* A still image or canvas retires the placeholder; model-viewer manages its
   own poster slot, so it is deliberately not in this list. */
.hero-figure:has(> canvas) .hero-skeleton:not([slot]),
.hero-figure:has(> img) .hero-skeleton:not([slot]),
.hero-figure:has(> video) .hero-skeleton:not([slot]) { display: none; }

/* ---- 4.4a <model-viewer> ----
   Sized here rather than by attribute for two reasons: the element is a
   custom tag that lays out as INLINE until its module executes — which would
   shift the page on a slow connection — and its default size is 300x150,
   which would ignore the figure's ratio entirely. Explicit block dimensions
   close both gaps before the script arrives. */
.hero-figure > model-viewer {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;

    /* Transparent, so the glow behind it shows through in both themes. */
    background-color: transparent;
    --poster-color: transparent;
    --progress-bar-color: var(--color-primary);
    --progress-mask: transparent;
}

/* No focus ring on the viewer. camera-controls makes the element focusable,
   which paints the UA's default highlight over the model. The real controls
   (arrows, dots, buttons) keep their rings, so keyboard focus is still
   visible everywhere it carries meaning. */
.hero-figure > model-viewer:focus,
.hero-figure > model-viewer:focus-visible,
.hero-figure > model-viewer:focus-within,
.hero-figure > model-viewer:active {
    outline: none;
    box-shadow: none;
    -webkit-tap-highlight-color: transparent;
}

/* The poster fills the viewer, so the skeleton occupies exactly the box the
   model will occupy — the swap is in place, with no blank frame. */
.hero-figure > model-viewer > [slot="poster"] { position: absolute; inset: 0; }

/* ---- 4.5 Loading and failure states ----
   Both sit in the same box at the same inset, and neither carries a surface
   — they read as part of the glow rather than as a card on top of it. */
.hero-fallback[hidden] { display: none; }

.hero-skeleton,
.hero-fallback {
    position: absolute;
    inset: 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--sp-3);
    padding: var(--sp-5);
    text-align: center;
    background: transparent;
}

.hero-skeleton { animation: heroPulse 2.4s var(--ease) infinite; }

@keyframes heroPulse {
    0%, 100% { opacity: 0.62; }
    50%      { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .hero-skeleton { animation: none; opacity: 0.85; }
}

.hero-skeleton-glyph {
    display: grid;
    place-items: center;
    width: var(--control-h-lg);
    height: var(--control-h-lg);
    border-radius: var(--r-pill);
    background: var(--accent-soft);
    color: var(--accent);
}

.hero-skeleton-label {
    font-family: var(--font-display);
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--text-muted);
}

.hero-skeleton-spec {
    font-size: 0.75rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-faint);
}

/* -------------------------------------------- 4.6 STAGE 2: THE REVEAL -- */
/* Sits directly below the 100vh hero. `position: relative` plus a page-level
   z-index puts this whole section ABOVE the hero in paint order, so the
   blurred glow behind the 3D element cannot bleed over this type as the user
   scrolls past. */
.reveal-stage {
    position: relative;
    z-index: var(--z-page);
    /* Generous, so the jump out of a full-height hero has room to breathe
       rather than landing straight on the type. */
    padding-block: clamp(var(--sp-9), 16vh, 11rem);
    background: var(--bg-body);
}

.reveal-stage-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-4);
    text-align: center;
}

.reveal-mark {
    margin: 0;
    font-family: var(--font-display);
    line-height: 0.92;
    text-wrap: balance;
}

.reveal-mark-lead {
    display: block;
    font-size: clamp(1.125rem, 3.2vw, 2rem);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.reveal-mark-word {
    display: block;
    font-size: clamp(4.5rem, 18vw, 12rem);
    font-weight: 800;
    letter-spacing: -0.055em;
    color: var(--text);
}

.reveal-sub {
    margin: 0;
    max-width: 44ch;
    font-size: clamp(1rem, 1.6vw, 1.1875rem);
    color: var(--text-muted);
    text-wrap: balance;
}

/* ------------------------------------------------------- 5. SURFACES --- */
/* One reusable surface. Cards, panels and steps all use it — no near-
   duplicate classes. */
.panel {
    background: var(--bg-surface);
    border-radius: var(--r-xl);
    box-shadow: var(--shadow-card);
    padding: clamp(var(--sp-5), 3vw, var(--sp-7));
}

.panel-flush { padding: 0; overflow: hidden; }

/* ------------------------------------------------- 6. MEDIA SLOTS ------ */
/* Aspect-ratio is the CLS guarantee: the box is known before any image
   exists, so dropping artwork in changes nothing about the layout. */
.media {
    position: relative;
    width: 100%;
    aspect-ratio: 1 / 1;
    display: grid;
    place-items: center;
    overflow: hidden;
    border-radius: var(--r-xl);
    background: var(--bg-field);
    box-shadow: var(--shadow-card);
}

.media-wide { aspect-ratio: 16 / 10; }
.media-tall { aspect-ratio: 4 / 5; }
.media-round { border-radius: var(--r-pill); }

.media-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-5);
    text-align: center;
    color: var(--text-faint);
}

.media-glyph {
    width: 3rem;
    height: 3rem;
    border-radius: var(--r-lg);
    display: grid;
    place-items: center;
    background: var(--bg-chip);
    color: var(--text-muted);
}

.media-label { font-size: 0.8125rem; font-weight: 600; color: var(--text-muted); }
.media-spec { font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; }

/* Real artwork fills the slot and retires the placeholder chrome. */
.media > img,
.media > video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.media:has(> img) .media-inner,
.media:has(> video) .media-inner { display: none; }

/* ------------------------------------------------------- 7. SECTIONS --- */
.section-head {
    max-width: 34ch;
    margin-inline: auto;
    margin-block-end: clamp(var(--sp-7), 5vh, var(--sp-9));
    text-align: center;
}

.section-title {
    font-size: clamp(1.625rem, 3.6vw, 2.75rem);
    font-weight: 800;
    letter-spacing: -0.035em;
    line-height: 1.12;
    text-wrap: balance;
}

.section-sub {
    margin-block-start: var(--sp-3);
    font-size: clamp(0.9375rem, 1.3vw, 1.0625rem);
    line-height: 1.6;
    color: var(--text-muted);
}

/* One responsive grid primitive, reused by cards and steps alike. */
.grid-auto {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
    gap: clamp(var(--sp-4), 2.5vw, var(--sp-6));
}

.card-title { font-size: 1.125rem; font-weight: 700; letter-spacing: -0.02em; margin-block-end: var(--sp-2); }
.card-text { font-size: 0.9375rem; line-height: 1.65; color: var(--text-muted); }

.step { text-align: center; }

.step-num {
    width: 2.75rem;
    height: 2.75rem;
    margin-inline: auto;
    margin-block-end: var(--sp-4);
    border-radius: var(--r-pill);
    display: grid;
    place-items: center;
    background: var(--accent);
    color: var(--on-accent);
    font-size: 1rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
}

/* ---- 7.1 Figures ---- */
.figure-grid { display: grid; gap: clamp(var(--sp-5), 4vw, var(--sp-8)); text-align: center; }

@media (min-width: 45rem) {
    .figure-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.figure-value {
    display: block;
    min-width: 3ch;                  /* counting digits never resize the box */
    font-size: clamp(2.25rem, 6vw, 4rem);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -0.04em;
    font-variant-numeric: tabular-nums;
    color: var(--accent);
}

.figure-label { margin-block-start: var(--sp-3); font-size: 0.9375rem; color: var(--text-muted); }

/* ---- 7.2 Closing call to action ---- */
.cta { text-align: center; }
.cta-actions {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: var(--sp-3);
    margin-block-start: clamp(var(--sp-6), 4vh, var(--sp-7));
}

/* --------------------------------------------------------- 8. FOOTER --- */
.site-foot { padding-block: var(--sp-7) var(--sp-8); }

.foot-inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--sp-3);
    font-size: 0.8125rem;
    color: var(--text-faint);
    text-align: center;
}

/* -------------------------------------------------------- 9. REVEALS --- */
/* Opacity and transform only — neither participates in layout, so the page
   is fully laid out at first paint and animating cannot shift it. */
/* The hidden state is scoped to .js — set pre-paint by the inline head
   script. Without that gate a script failure would leave every reveal target
   permanently at opacity 0, i.e. a blank page. */
.js [data-reveal] {
    opacity: 0;
    transform: translate3d(0, var(--reveal-y, 1.25rem), 0);
    transition: opacity 600ms cubic-bezier(0.16, 1, 0.3, 1),
                transform 600ms cubic-bezier(0.16, 1, 0.3, 1);
    transition-delay: var(--d, 0ms);
    will-change: opacity, transform;
}

.js [data-reveal].is-in { opacity: 1; transform: none; }
.js [data-reveal].is-done { will-change: auto; }

/* Stage 2 gets a longer throw and a slower curve than the small in-page
   reveals — it is the moment the section is built around. Neither property
   participates in layout, so the travel cannot shift anything. */
.js .reveal-mark {
    --reveal-y: 50px;
    transition-duration: 900ms;
}

.js .reveal-sub { --reveal-y: 28px; transition-duration: 760ms; }

.nav-sentinel { position: absolute; inset-block-start: 0; inset-inline: 0; block-size: 1px; pointer-events: none; }

/* ------------------------------- 10. AUTH DIALOG SUPPORT --------------- */
/* The dialogs themselves come from global.css. Only the auth-specific bits
   live here, and they exist to keep error UI from moving anything. */

.auth-intro {
    display: flex;
    gap: var(--sp-3);
    padding: var(--sp-4);
    margin-block-end: var(--sp-4);
    border-radius: var(--r-md);
    background: var(--bg-field);
}

.auth-intro .icon { flex: 0 0 1.125rem; color: var(--accent); margin-block-start: 1px; }
.auth-intro-text { font-size: 0.8125rem; line-height: 1.6; color: var(--text-muted); }

/* Present in the DOM at a fixed height from first paint. A server error
   appearing changes colour and text only — never the dialog's size. */
.auth-status {
    display: flex;
    align-items: flex-start;
    gap: var(--sp-2);
    min-height: 2.25rem;
    margin-block-start: var(--sp-2);
    padding: var(--sp-2) var(--sp-3);
    border-radius: var(--r-sm);
    font-size: 0.8125rem;
    line-height: 1.45;
    background: transparent;
    color: transparent;
    transition: background-color var(--t-base), color var(--t-base);
}

.auth-status .icon { width: 0.9375rem; height: 0.9375rem; flex: 0 0 0.9375rem; margin-block-start: 2px; opacity: 0; }
.auth-status.is-error { background: var(--danger-soft); color: var(--danger); }
.auth-status.is-ok { background: var(--accent-soft); color: var(--accent); }
.auth-status.is-error .icon,
.auth-status.is-ok .icon { opacity: 1; }

.auth-alt {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--sp-3);
    margin-block-start: var(--sp-3);
    font-size: 0.8125rem;
    color: var(--text-muted);
}

.link-btn {
    padding: 0;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--accent);
    border-radius: var(--r-xs);
    transition: color var(--t-base);
}

.link-btn:hover { color: var(--accent-strong); text-decoration: underline; }
.link-btn:active { color: var(--accent-strong); }
.link-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ------------------------------------------------------ 11. RESPONSIVE - */
/* Type and spacing already scale continuously with clamp(); these rules only
   restack, and use min-width so the page is authored mobile-first. */
@media (max-width: 45rem) {
    .nav-link.hide-sm { display: none; }
    .cta-actions .btn { flex: 1 1 100%; }

    /* Switcher on its own line, then the two auth buttons side by side across
       the full width, so the tap targets stay generous at narrow widths.
       The explicit width is needed because .hero-info centres its children,
       which would otherwise shrink this row to its content. */
    .hero-actions { flex-direction: column; align-items: stretch; width: 100%; }
    .hero-switcher { justify-content: center; }
    .hero-auth { justify-content: center; }
    .hero-auth .btn { flex: 1 1 0; }

    /* Stage 1 is meant to be read without scrolling. At the default rhythm
       the stacked column runs ~115px past a 375x812 screen, putting the auth
       buttons below the fold — the one thing that must stay visible. These
       trims pull it back inside. Every one of them is spacing or type scale:
       the figure keeps its locked ratio, so none of this can cause a shift. */
    .hero { padding-block: var(--sp-5); }
    .hero-split { gap: var(--sp-5); }
    .hero-info { gap: var(--sp-3); }
    .hero-visual { --figure-w: min(62%, 13.5rem); }
    .hero-greeting { font-size: clamp(1.5rem, 6.4vw, 1.875rem); }
    .hero-character-desc { line-height: 1.55; min-height: calc(3 * 1.55em); }
}
