/* App styles on top of the MudBlazor theme (Theme/ArroTheme.cs).
   Brand tokens follow the live arrosystems.com Elementor kit; motion tokens
   and t-* transition classes are vendored from transitions.dev (see
   .claude/skills/motion-transitions). */

:root {
    /* Brand (arrosystems.com global kit) */
    --arro-navy: #042D49;
    --arro-navy-deep: #032338;
    --arro-green: #368604;
    --arro-green-dark: #2E7203;
    --arro-green-leaf: #79A349;
    --arro-blue: #11759D;
    --arro-sky: #1999CC;
    --arro-slate: #57586E;
    --arro-mist: #ECF0F6;
    --arro-ink: #232525;
    --arro-paper: #F6FAFC;

    /* Motion tokens (transitions.dev) */
    --stagger-dur: 500ms;
    --stagger-distance: 12px;
    --stagger-stagger: 60ms;
    --stagger-blur: 3px;
    --stagger-ease: cubic-bezier(0.22, 1, 0.36, 1);

    --tilt-perspective: 1000px;
    --tilt-return: 1000ms;
    --tilt-return-ease: cubic-bezier(0.22, 1, 0.36, 1);
    --tilt-follow: 400ms;
    --tilt-follow-ease: cubic-bezier(0.22, 1, 0.36, 1);
    --tilt-glare-opacity: 0.32;
    --tilt-glare-fade: 300ms;
    --tilt-glare-ease: cubic-bezier(0.22, 1, 0.36, 1);

    --digit-dur: 500ms;
    --digit-distance: 8px;
    --digit-stagger: 70ms;
    --digit-blur: 2px;
    --digit-ease: cubic-bezier(0.34, 1.45, 0.64, 1);

    --tabs-dur: 250ms;
    --tabs-ease: cubic-bezier(0.22, 1, 0.36, 1);

    --shake-distance: 6px;
    --shake-overshoot: 4px;
    --shake-dur-a: 80ms;
    --shake-dur-b: 60ms;
    --shake-ease: cubic-bezier(0.22, 1, 0.36, 1);
    --revert-dur: 280ms;

    --check-opacity-dur: 500ms;
    --check-rotate-dur: 500ms;
    --check-rotate-from: 80deg;
    --check-bob-dur: 500ms;
    --check-y-amount: 40px;
    --check-blur-dur: 500ms;
    --check-blur-from: 10px;
    --check-path-dur: 500ms;
    --check-path-delay: 80ms;
    --check-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
    --check-ease-bob: cubic-bezier(0.34, 1.35, 0.64, 1);

    --page-slide-dur: 250ms;
    --page-slide-distance: 8px;
    --page-blur: 3px;
    --page-slide-ease: cubic-bezier(0.22, 1, 0.36, 1);

    --skel-reveal-dur: 400ms;
    --skel-reveal-blur: 2px;
    --skel-reveal-ease: ease-in-out;
    --skel-pulse-dur: 1200ms;

    /* ── Semantic surface tokens (wp-poc-dark-mode) ──────────────────────────
       The bespoke (non-MudBlazor) console surfaces read these instead of raw hex
       so a single html.arro-dark override re-themes them all. Light = the values
       they used to hard-code; dark = the WCAG-AA-verified dark set below. */
    --surface-card: #ffffff;
    --surface-inset: var(--arro-mist);
    --surface-strip: var(--arro-mist);
    --border-card: var(--arro-mist);
    --card-shadow: rgba(4, 45, 73, 0.06);
    --text-strong: var(--arro-navy);
    --text-muted: var(--arro-slate);
    --accent-green: var(--arro-green);
    --accent-blue: var(--arro-blue);
    --pill-surface: #ffffff;
    --pill-shadow: rgba(4, 45, 73, 0.22);
    --tab-inactive: rgba(35, 37, 37, 0.72); /* AA on --arro-mist (F7/F8 nudge) */
    --diagram-frame: var(--arro-paper);
    --diagram-code-bg: var(--arro-mist);
    --nav-hover: rgba(4, 45, 73, 0.08);
}

/* Effective dark theme (System→OS resolved, or a forced Dark choice). The class is
   stamped on <html> synchronously pre-Blazor (js/arro-theme.js) and kept in sync by
   ThemeService, so these tokens + the diagram swap never lag the MudBlazor palette. */
html.arro-dark {
    --surface-card: #13212F;
    --surface-inset: #1B2B3A;
    --surface-strip: #172431;
    --border-card: rgba(255, 255, 255, 0.10);
    --card-shadow: rgba(0, 0, 0, 0.40);
    --text-strong: #E6EDF3;      /* ~15:1 on the dark base */
    --text-muted: #9DB0C5;       /* ~7.4:1 on the dark surface */
    --accent-green: #8FC65B;     /* ~8:1 on the dark card */
    --accent-blue: #5BB4E0;      /* ~7:1 on the dark card */
    --pill-surface: #26384A;
    --pill-shadow: rgba(0, 0, 0, 0.55);
    --tab-inactive: rgba(230, 237, 243, 0.72); /* parity with the light nudge (F7/F8) */
    --diagram-frame: #0D1A29;
    --diagram-code-bg: #1C3350;
    --nav-hover: rgba(255, 255, 255, 0.12);
}

::selection {
    background: var(--arro-green);
    color: #ffffff;
}

/* FocusOnNavigate moves focus to the page h1 for screen readers; headings
   are not interactive, so suppress the visible ring. */
h1:focus,
h1:focus-visible {
    outline: none;
}

/* ── Skip-to-content link (a11y) ──────────────────────────────────────────
   Off-screen until focused; the first Tab stop on an app page jumps past the app bar to #main. */
.skip-link {
    position: fixed;
    left: 8px;
    top: -60px;
    z-index: 3000;
    padding: 10px 16px;
    border-radius: 8px;
    background: var(--arro-navy);
    color: #ffffff;
    font: 600 0.85rem 'Lexend Deca', sans-serif;
    text-decoration: none;
    transition: top 150ms var(--tabs-ease);
}

.skip-link:focus {
    top: 8px;
    outline: 2px solid var(--arro-green);
    outline-offset: 2px;
}

/* ── App bar (console shell) ──────────────────────────────────────────── */

/* Signature accent carried over from the ARRO Mobile shell (its
   AppBarGreenBorder rule), recolored to the marketing-site green. */
.AppBarGreenBorder {
    border-bottom: 4px solid var(--arro-green);
}

.appbar-logo {
    height: 26px;
    display: block;
}

/* Theme-gated wordmark swap (wp-poc-dark-mode): the navy logo on light surfaces, the
   light logo on dark surfaces. Used by the console app bar + the login card, whose
   surfaces flip with the theme (the navy landing/login NAVs always use the light logo). */
.theme-logo--dark { display: none; }
html.arro-dark .theme-logo--light { display: none; }
html.arro-dark .theme-logo--dark { display: block; }

.brand-sub {
    opacity: .6;
    font-weight: 500;
}

/* This build's version stamp, left of the bell — same muted treatment as .brand-sub.
   The full version+sha rides the title tooltip; the bar shows the compact form. */
.navbar-version {
    font-size: .8rem;
    font-weight: 500;
    opacity: .75;
    letter-spacing: .02em;
    white-space: nowrap;
    margin-right: 4px;
    cursor: default;
}

/* The user-menu copy of the version stamp is the PHONE placement — desktop keeps the
   app-bar stamp, so both the entry and its divider stay hidden until the ≤600px nav
   pass below swaps the two surfaces. */
.user-menu-version,
.user-menu-version-divider {
    display: none;
}

.env-chip { font-weight: 600; }

.avatar-initials {
    background: var(--arro-navy);
    color: #fff;
    font-weight: 600;
}

/* Navy is invisible on the dark app bar — lift the initials chip so the avatar reads. */
html.arro-dark .avatar-initials { background: #22415C; }

/* ── Theme toggle (wp-poc-dark-mode) ──────────────────────────────────────
   Leads the identity surface on every nav; inherits the nav's text colour so it
   is dark on the white app bar and white on the navy landing/login navs. */
.nav-actions {
    display: flex;
    align-items: center;
    gap: 4px;
}

.theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: inherit;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background-color 150ms ease-out;
}

.theme-toggle:hover { background: var(--nav-hover); }

.theme-toggle:focus-visible {
    outline: 2px solid var(--arro-green);
    outline-offset: 2px;
}

/* On the brand-navy landing/login navs the surrounding ink is dark — force the
   toggle white so it reads on navy in both light and dark app themes. */
.landing-nav .theme-toggle,
.login-nav .theme-toggle { color: rgba(255, 255, 255, 0.92); }

.landing-nav .theme-toggle:hover,
.login-nav .theme-toggle:hover { background: rgba(255, 255, 255, 0.12); }

/* Icon-swap: the icon is re-keyed per mode, so this replays on every cycle
   (motion-transitions icon-swap recipe). Reduced-motion collapses it to instant. */
.theme-toggle-icon {
    display: inline-flex;
    animation: theme-icon-in 260ms var(--tabs-ease);
}

@keyframes theme-icon-in {
    from { opacity: 0; transform: rotate(-90deg) scale(0.7); }
    to { opacity: 1; transform: none; }
}

/* ── Shared user menu — the one top-nav identity surface (Phase 9e) ────── */
.user-menu-activator {
    display: flex;
    align-items: center;
    border: 0;
    padding: 0;
    background: transparent;
    cursor: pointer;
}

.user-avatar {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    object-fit: cover;
    display: block;
    /* Reads on both the white app bar and the navy landing nav. */
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.65);
}

.user-avatar--large {
    width: 44px;
    height: 44px;
    box-shadow: none;
}

.user-menu-identity {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 220px;
}

/* ── transitions.dev: texts reveal (hero copy) ───────────────────────── */

.t-stagger-line {
    display: block;
    opacity: 0;
    transform: translateY(var(--stagger-distance));
    filter: blur(var(--stagger-blur));
    transition:
        opacity var(--stagger-dur) var(--stagger-ease),
        transform var(--stagger-dur) var(--stagger-ease),
        filter var(--stagger-dur) var(--stagger-ease);
    will-change: transform, opacity, filter;
}

.t-stagger-line--2 { transition-delay: var(--stagger-stagger); }
.t-stagger-line--3 { transition-delay: calc(var(--stagger-stagger) * 2); }
.t-stagger-line--4 { transition-delay: calc(var(--stagger-stagger) * 3); }

.t-stagger.is-shown .t-stagger-line {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
}

/* ── transitions.dev: card hover tilt (hero visual) ──────────────────── */

.t-tilt { touch-action: none; }

.t-tilt-card {
    position: relative;
    transform:
        perspective(var(--tilt-perspective))
        rotateX(var(--tilt-rx, 0deg))
        rotateY(var(--tilt-ry, 0deg));
    transform-style: preserve-3d;
    transition: transform var(--tilt-return) var(--tilt-return-ease);
    will-change: transform;
}

.t-tilt-card.is-tilting {
    transition: transform var(--tilt-follow) var(--tilt-follow-ease);
}

/* Framed variant clips the glare to the surface; used on solid tiles. */
.t-tilt-card--framed {
    border-radius: 16px;
    overflow: hidden;
}

.t-tilt-glare {
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0;
    mix-blend-mode: screen;
    background:
        radial-gradient(circle 95px at var(--tilt-gx, 50%) var(--tilt-gy, 50%),
            rgba(255, 255, 255, 0.48), rgba(255, 255, 255, 0.06) 52%, rgba(255, 255, 255, 0) 84%),
        radial-gradient(circle 200px at var(--tilt-gx, 50%) var(--tilt-gy, 50%),
            rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0.04) 58%, rgba(255, 255, 255, 0) 78%),
        radial-gradient(circle 360px at var(--tilt-gx, 50%) var(--tilt-gy, 50%),
            rgba(255, 255, 255, 0.10), rgba(255, 255, 255, 0) 88%);
    transition: opacity var(--tilt-glare-fade) var(--tilt-glare-ease);
}

.t-tilt.is-hover .t-tilt-glare { opacity: var(--tilt-glare-opacity); }

/* ── transitions.dev: number pop-in (console uptime) ─────────────────── */

@keyframes t-digit-pop-in {
    0% {
        transform: translate(0, var(--digit-distance));
        opacity: 0;
        filter: blur(var(--digit-blur));
    }
    100% { transform: translate(0, 0); opacity: 1; filter: blur(0); }
}

.t-digit-group {
    display: inline-flex;
    align-items: baseline;
}

.t-digit {
    display: inline-block;
    will-change: transform, opacity, filter;
}

.t-digit-group.is-animating .t-digit {
    animation: t-digit-pop-in var(--digit-dur) var(--digit-ease) both;
}

.t-digit-group.is-animating .t-digit[data-stagger="1"] { animation-delay: var(--digit-stagger); }
.t-digit-group.is-animating .t-digit[data-stagger="2"] { animation-delay: calc(var(--digit-stagger) * 2); }

/* ── transitions.dev: tabs sliding (equal-width segmented control) ───── */

.t-tabs {
    position: relative;
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    padding: 4px;
    border-radius: 999px;
    background: var(--surface-strip);
    isolation: isolate;
}

.t-tab {
    appearance: none;
    border: 0;
    background: transparent;
    height: 38px;
    padding: 4px 18px;
    font: 600 0.9rem 'Lexend Deca', sans-serif;
    color: var(--tab-inactive);
    cursor: pointer;
    border-radius: 999px;
    z-index: 1;
    transition: color var(--tabs-dur) var(--tabs-ease);
    white-space: nowrap;
}

/* Keyboard focus must paint its own ring — selection (the sliding pill) is not a focus
   indicator, and the strips' edge-fade lift depends on a ring existing to protect. */
.t-tab:focus-visible {
    outline: 3px solid var(--accent-green, #79A349);
    outline-offset: 2px;
}

.t-tab:hover,
.t-tab[aria-selected="true"] { color: var(--text-strong); }

/* Equal-width tabs let the pill position derive from the selected index
   alone, so Blazor can drive it without measuring the DOM. */
.t-tabs-pill {
    position: absolute;
    top: 4px;
    bottom: 4px;
    left: 4px;
    width: calc((100% - 8px) / var(--tab-count, 3));
    background: var(--pill-surface);
    border-radius: 999px;
    box-shadow: 0 1px 4px var(--pill-shadow);
    transform: translateX(calc(100% * var(--tab-index, 0)));
    transition: transform var(--tabs-dur) var(--tabs-ease);
    will-change: transform;
    z-index: 0;
    pointer-events: none;
}

/* ── transitions.dev: error state shake (login form) ─────────────────── */

.t-input {
    transition: border-color 150ms ease-out;
    will-change: transform;
}

.t-input.is-shaking {
    animation: t-input-shake calc(var(--shake-dur-a) * 2 + var(--shake-dur-b) * 2) linear;
}

@keyframes t-input-shake {
    0%     { transform: translateX(0); animation-timing-function: var(--shake-ease); }
    28.57% { transform: translateX(var(--shake-distance)); animation-timing-function: var(--shake-ease); }
    57.14% { transform: translateX(calc(var(--shake-distance) * -1)); animation-timing-function: var(--shake-ease); }
    78.57% { transform: translateX(var(--shake-overshoot)); animation-timing-function: var(--shake-ease); }
    100%   { transform: translateX(0); }
}

.t-error-msg {
    opacity: 0;
    visibility: hidden;
    color: #b3261e;
    font-size: 0.85rem;
    margin: 6px 2px 0;
    transition:
        opacity var(--revert-dur) ease-out,
        visibility 0s linear var(--revert-dur);
}

.t-input-wrap.is-error .t-error-msg {
    opacity: 1;
    visibility: visible;
    transition:
        opacity var(--revert-dur) ease-out,
        visibility 0s linear 0s;
}

/* ── transitions.dev: success check (login confirmation) ─────────────── */

.t-success-check {
    display: inline-block;
    transform-origin: center;
    opacity: 0;
    will-change: transform, opacity, filter;
}

.t-success-check svg { display: block; overflow: visible; }

.t-success-check svg path {
    stroke-dasharray: 48;
    stroke-dashoffset: 48;
}

.t-success-check[data-state="in"] {
    animation:
        t-check-fade   var(--check-opacity-dur) var(--check-ease-out) forwards,
        t-check-rotate var(--check-rotate-dur)  var(--check-ease-out) forwards,
        t-check-blur   var(--check-blur-dur)    var(--check-ease-out) forwards,
        t-check-bob    var(--check-bob-dur)     var(--check-ease-bob) forwards;
}

.t-success-check[data-state="in"] svg path {
    animation: t-check-draw var(--check-path-dur) var(--check-ease-out) var(--check-path-delay) forwards;
}

@keyframes t-check-fade   { from { opacity: 0; } to { opacity: 1; } }
@keyframes t-check-rotate { from { transform: rotate(var(--check-rotate-from)); } to { transform: rotate(0deg); } }
@keyframes t-check-blur   { from { filter: blur(var(--check-blur-from)); } to { filter: blur(0); } }
@keyframes t-check-bob    { from { translate: 0 var(--check-y-amount); } to { translate: 0 0; } }
@keyframes t-check-draw   { to { stroke-dashoffset: 0; } }

/* ── Scroll reveal (landing sections; classes flipped by arro-motion.js) */

.reveal {
    opacity: 0;
    transform: translateY(18px);
    filter: blur(var(--stagger-blur));
    transition:
        opacity 600ms var(--stagger-ease),
        transform 600ms var(--stagger-ease),
        filter 600ms var(--stagger-ease);
    transition-delay: calc(var(--reveal-index, 0) * 80ms);
}

.reveal.is-shown {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
}

/* ── Console panel enter (page fade, keyed per tab) ──────────────────── */

@keyframes panel-enter {
    from {
        opacity: 0;
        transform: translateY(var(--page-slide-distance));
        filter: blur(var(--page-blur));
    }
    to { opacity: 1; transform: translateY(0); filter: blur(0); }
}

.panel-enter {
    animation: panel-enter var(--page-slide-dur) var(--page-slide-ease) both;
}

/* ── Landing page ─────────────────────────────────────────────────────── */

.landing {
    min-height: 100dvh;
    background: var(--arro-navy);
    color: #ffffff;
    font-family: 'Lexend Deca', sans-serif;
}

.landing-nav {
    max-width: 1160px;
    margin: 0 auto;
    padding: 22px 24px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.landing-logo {
    height: 30px;
    display: block;
}

.btn-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    border: 0;
    border-radius: 999px;
    padding: 12px 28px;
    font: 600 0.95rem 'Lexend Deca', sans-serif;
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: transform 200ms var(--stagger-ease), box-shadow 200ms var(--stagger-ease), background-color 200ms ease;
}

.btn-pill:active { transform: translateY(1px) scale(0.98); }

.btn-green {
    background: var(--arro-green);
    color: #ffffff;
}

.btn-green:hover {
    background: var(--arro-green-dark);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.35);
    transform: translateY(-1px);
}

.btn-outline-light {
    background: transparent;
    color: #ffffff;
    box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.45);
}

.btn-outline-light:hover { box-shadow: inset 0 0 0 1.5px #ffffff; }

/* Hero: asymmetric split, copy left, tilting product shot right. */
.hero {
    max-width: 1160px;
    margin: 0 auto;
    padding: 40px 24px 72px;
    display: grid;
    grid-template-columns: minmax(0, 6fr) minmax(0, 6fr);
    gap: 40px;
    align-items: center;
}

.hero-headline {
    font-size: clamp(2.2rem, 4.8vw, 3.8rem);
    font-weight: 700;
    line-height: 1.08;
    letter-spacing: -0.015em;
    color: #ffffff;
    margin: 0 0 20px;
}

.hero-headline .accent { color: var(--arro-green-leaf); }

.hero-sub {
    font-size: 1.02rem;
    font-weight: 300;
    line-height: 1.65;
    color: rgba(255, 255, 255, 0.85);
    max-width: 32rem;
    margin: 0 0 30px;
}

.hero-ctas { display: flex; gap: 14px; flex-wrap: wrap; }

.hero-visual { margin: 0 auto; width: 100%; }

.hero-visual img {
    display: block;
    width: 100%;
    height: auto;
    filter: drop-shadow(0 30px 50px rgba(0, 0, 0, 0.45));
}

/* Trust wall directly under the hero (real agency seals). */
.trust {
    background: var(--arro-navy-deep);
    padding: 34px 24px;
}

.trust-inner {
    max-width: 1160px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    gap: 28px;
    flex-wrap: wrap;
    justify-content: center;
}

.trust p {
    margin: 0;
    font-size: 0.85rem;
    color: rgba(255, 255, 255, 0.6);
    white-space: nowrap;
}

.trust img {
    display: block;
    max-width: min(640px, 100%);
    height: auto;
}

/* Release flow strip. */
.flow {
    background: var(--arro-paper);
    color: var(--arro-ink);
    padding: 80px 24px;
}

.flow-inner { max-width: 1160px; margin: 0 auto; }

.flow h2 {
    font-size: clamp(1.6rem, 3vw, 2.2rem);
    font-weight: 700;
    color: var(--arro-navy);
    margin: 0 0 10px;
}

.flow-lede {
    font-size: 1rem;
    color: var(--arro-slate);
    max-width: 42rem;
    margin: 0 0 40px;
    line-height: 1.6;
}

.flow-steps {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 18px;
}

.flow-step {
    background: #ffffff;
    border: 1px solid var(--arro-mist);
    border-radius: 16px;
    padding: 24px 22px;
    box-shadow: 0 1px 3px rgba(4, 45, 73, 0.06);
}

.flow-step .glyph {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    border-radius: 12px;
    background: var(--arro-mist);
    color: var(--arro-green);
    margin-bottom: 14px;
    font-weight: 700;
}

.flow-step img { width: 26px; height: 26px; }

.flow-step h3 {
    font-size: 1rem;
    font-weight: 600;
    color: var(--arro-navy);
    margin: 0 0 6px;
}

.flow-step p {
    font-size: 0.88rem;
    line-height: 1.55;
    color: var(--arro-slate);
    margin: 0;
}

/* Bento: what the PoC proves. */
.bento {
    background: var(--arro-paper);
    color: var(--arro-ink);
    padding: 8px 24px 88px;
}

.bento-inner { max-width: 1160px; margin: 0 auto; }

.bento h2 {
    font-size: clamp(1.6rem, 3vw, 2.2rem);
    font-weight: 700;
    color: var(--arro-navy);
    margin: 0 0 40px;
}

.bento-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-auto-rows: minmax(190px, auto);
    gap: 18px;
}

.bento-tile {
    background: #ffffff;
    border-radius: 16px;
    padding: 26px;
    border: 1px solid var(--arro-mist);
    box-shadow: 0 1px 3px rgba(4, 45, 73, 0.06);
    overflow: hidden;
}

.bento-tile h3 {
    font-size: 1.02rem;
    font-weight: 600;
    color: var(--arro-navy);
    margin: 0 0 8px;
}

.bento-tile p {
    font-size: 0.9rem;
    line-height: 1.6;
    color: var(--arro-slate);
    margin: 0;
}

.bento-tile--proof {
    grid-column: span 2;
    background: var(--arro-navy);
    border-color: var(--arro-navy);
}

.bento-tile--proof h3 { color: #ffffff; }
.bento-tile--proof p { color: rgba(255, 255, 255, 0.72); }

.bento-tile--proof pre {
    margin: 16px 0 0;
    padding: 14px 16px;
    background: rgba(255, 255, 255, 0.07);
    border-radius: 10px;
    font: 0.78rem/1.6 ui-monospace, Consolas, monospace;
    color: #9fd77c;
    overflow-x: auto;
}

.bento-tile--proof .proof-live {
    margin: 10px 0 0;
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.78rem;
    color: rgba(255, 255, 255, 0.55);
}

.live-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--arro-green, #79A349);
    box-shadow: 0 0 0 3px rgba(121, 163, 73, 0.25);
}

.bento-tile--screen {
    grid-row: span 2;
    padding: 0;
    background: linear-gradient(165deg, var(--arro-blue), var(--arro-navy));
    border: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

.bento-tile--screen img {
    display: block;
    width: 88%;
    height: auto;
}

.bento-tile--mist { background: var(--arro-mist); border-color: var(--arro-mist); }

/* Field section: storm image + resilience copy. */
.field {
    background: var(--arro-paper);
    padding: 0 24px 96px;
}

.field-inner {
    max-width: 1160px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: 48px;
    align-items: center;
}

.field img {
    display: block;
    width: 100%;
    height: auto;
}

.field h2 {
    font-size: clamp(1.6rem, 3vw, 2.2rem);
    font-weight: 700;
    color: var(--arro-navy);
    margin: 0 0 14px;
}

.field p {
    font-size: 0.95rem;
    line-height: 1.7;
    color: var(--arro-slate);
    margin: 0 0 12px;
}

.field ul {
    margin: 18px 0 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 10px;
}

.field li {
    display: flex;
    gap: 10px;
    font-size: 0.92rem;
    color: var(--arro-ink);
}

.field li::before {
    content: "";
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    margin-top: 2px;
    background: var(--arro-green);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M9 16.2 4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z'/%3E%3C/svg%3E") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M9 16.2 4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Footer. */
.landing-footer {
    background: var(--arro-navy);
    /* Extra bottom room so the fixed PWA update toast (bottom: 24px + safe-area)
       never lands on the footer nav/status — the .mud-main-content reservation is
       app-pages only; the landing page uses this layout (UX #11). */
    padding: 48px 24px calc(48px + 72px + env(safe-area-inset-bottom, 0px));
}

.landing-footer-inner {
    max-width: 1160px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    flex-wrap: wrap;
}

.landing-footer img { height: 24px; display: block; }

.landing-footer small {
    color: rgba(255, 255, 255, 0.55);
    font-size: 0.78rem;
    line-height: 1.5;
    max-width: 44rem;
}

.landing-footer nav { display: flex; gap: 20px; }

.landing-footer nav a {
    color: rgba(255, 255, 255, 0.75);
    font-size: 0.85rem;
    text-decoration: none;
}

.landing-footer nav a:hover { color: #ffffff; }

.landing-footer .footer-status {
    color: rgba(255, 255, 255, 0.45);
    font-size: 0.78rem;
    font-variant-numeric: tabular-nums;
}

/* ── Login page ───────────────────────────────────────────────────────── */

.login-page {
    min-height: 100dvh;
    background:
        radial-gradient(1100px 560px at 85% -10%, rgba(17, 117, 157, 0.5), transparent 60%),
        var(--arro-navy);
    font-family: 'Lexend Deca', sans-serif;
    display: flex;
    flex-direction: column;
}

.login-nav {
    padding: 22px 24px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.login-nav img { height: 28px; display: block; }

/* Tenant-allowlist rejection (Phase 9e): signed in at Microsoft, not authorized here. */
.login-tenant-error {
    margin: 0 0 16px;
    padding: 10px 12px;
    border-radius: 8px;
    background: rgba(176, 32, 32, 0.08);
    font-size: 0.85rem;
    text-align: left;
}

.login-center {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}

.login-card {
    width: min(430px, 100%);
    background: #ffffff;
    border-radius: 16px;
    padding: 36px 34px;
    box-shadow: 0 24px 80px rgba(0, 0, 0, 0.45);
    color: var(--arro-ink);
}

.login-card .login-logo { height: 26px; display: block; }

.login-card h1 {
    font-size: 1.45rem;
    font-weight: 700;
    color: var(--arro-navy);
    margin: 20px 0 4px;
}

.login-card .login-sub {
    font-size: 0.9rem;
    color: var(--arro-slate);
    margin: 0 0 26px;
}

.btn-entra {
    width: 100%;
    background: var(--arro-navy);
    color: #ffffff;
}

.btn-entra:hover {
    background: var(--arro-navy-deep);
    box-shadow: 0 6px 20px rgba(4, 45, 73, 0.35);
}

.login-divider {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 22px 0;
    color: var(--arro-slate);
    font-size: 0.8rem;
}

.login-divider::before,
.login-divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--arro-mist);
}

.login-field { margin-bottom: 14px; }

.login-field label {
    display: block;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--arro-navy);
    margin-bottom: 6px;
}

.login-field input {
    width: 100%;
    box-sizing: border-box;
    border: 1.5px solid rgba(35, 37, 37, 0.22);
    border-radius: 10px;
    padding: 12px 14px;
    font: 400 0.95rem 'Lexend Deca', sans-serif;
    color: var(--arro-ink);
    background: #fff;
    outline: none;
    transition: border-color 150ms ease-out, box-shadow 150ms ease-out;
}

.login-field input:focus {
    border-color: var(--arro-green);
    box-shadow: 0 0 0 3px rgba(54, 134, 4, 0.16);
}

.t-input.is-error input { border-color: #b3261e; }

.btn-signin { width: 100%; }

.login-hint {
    font-size: 0.78rem;
    color: var(--arro-slate);
    margin-top: 20px;
    line-height: 1.5;
}

.login-busy {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 28px 0 10px;
}

/* Sign-in stall recovery (SignInStallGuard): bounded "Completing sign-in" spinner. */
.login-stall {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
    padding: 20px 0 10px;
}

.login-stall .login-tenant-error {
    margin: 0;
    color: #b3261e;
}

/* Shimmer text while the simulated Entra redirect is in flight. */
.shimmer-text {
    font-size: 0.9rem;
    background: linear-gradient(90deg, #7c7c7c 40%, #0d0d0d 50%, #7c7c7c 60%) 0 0 / 400% 100% text;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    animation: shimmer-sweep 2000ms linear infinite;
}

/* ── Login card — dark theme (wp-poc-dark-mode) ───────────────────────────
   The login page stays brand-navy in both modes; in dark the white card drops to
   the dark surface so it doesn't glare against the navy field. Inputs/buttons/error
   copy lift to AA on the dark card. */
html.arro-dark .login-card {
    background: var(--surface-card);
    color: var(--text-strong);
    box-shadow: 0 24px 80px rgba(0, 0, 0, 0.60);
}

html.arro-dark .login-card h1 { color: var(--text-strong); }

html.arro-dark .login-card .login-sub,
html.arro-dark .login-hint,
html.arro-dark .login-divider { color: var(--text-muted); }

html.arro-dark .login-divider::before,
html.arro-dark .login-divider::after { background: var(--border-card); }

html.arro-dark .login-field label { color: var(--text-strong); }

html.arro-dark .login-field input {
    background: #0E1A26;
    color: var(--text-strong);
    border-color: rgba(255, 255, 255, 0.24);
}

html.arro-dark .btn-entra { background: #1B3B57; }
html.arro-dark .btn-entra:hover { background: #24506F; }

html.arro-dark .login-tenant-error { background: rgba(176, 32, 32, 0.22); color: #F2B8B5; }

html.arro-dark .t-input.is-error input { border-color: #F2777A; }

html.arro-dark .t-error-msg,
html.arro-dark .login-stall .login-tenant-error { color: #F2777A; }

html.arro-dark .shimmer-text {
    background: linear-gradient(90deg, #64748b 40%, #d7e3f0 50%, #64748b 60%) 0 0 / 400% 100% text;
    -webkit-background-clip: text;
    background-clip: text;
}

@keyframes shimmer-sweep {
    from { background-position: 100% 0; }
    to   { background-position: 0 0; }
}

.login-success {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 28px 0 12px;
}

.login-success .t-success-check { color: var(--arro-green); }

.login-success p { font-weight: 600; margin: 18px 0 2px; }

.login-success small { color: var(--arro-slate); }

/* ── Console page ─────────────────────────────────────────────────────── */

.stat-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 14px;
    margin-bottom: 24px;
}

.stat-tile {
    background: var(--surface-card);
    border-radius: 16px;
    padding: 18px 20px;
    border: 1px solid var(--border-card);
    box-shadow: 0 1px 3px var(--card-shadow);
}

.stat-tile .stat-label {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--text-muted);
    margin-bottom: 6px;
}

.stat-tile .stat-value {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--text-strong);
    font-variant-numeric: tabular-nums;
    word-break: break-all;
}

/* Slot color is semantic: the blue/green deployment target. */
.stat-value--blue { color: var(--accent-blue); }
.stat-value--green { color: var(--accent-green); }

/* Deployment-info table: fixed label column, monospace values. */
.row-label {
    width: 14rem;
    text-align: left;
    font-weight: 600;
    opacity: .8;
}

.row-value {
    font-family: ui-monospace, Consolas, monospace;
    word-break: break-all;
}

.pipeline-card { border-left: 4px solid var(--arro-green); }

/* CollapsibleIntro (POC-U3): full prose on md+ (toggle hidden, nothing changes);
   the xs clamp + toggle live in the responsive block below. */
.intro-blurb-toggle { display: none; }

/* ── Pre-Blazor loading shell ─────────────────────────────────────────── */

.app-loading {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    font-family: 'Lexend Deca', system-ui, sans-serif;
    background: #042D49;
    color: #fff;
}

/* The instance icon: js/instance-badge.js swaps in the badged variant (dev/qa/govdev)
   before Blazor boots; prod keeps the plain mark. */
.app-loading-icon {
    width: 76px;
    height: 76px;
    margin-bottom: 1.15rem;
    border-radius: 18px;
    /* The icon's own navy tile vanishes against the identical navy splash —
       a soft ring keeps the app-icon silhouette readable. */
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.22);
    animation: loading-pulse 1600ms ease-in-out infinite;
}

.app-loading-env {
    margin-top: .55rem;
    font-size: .78rem;
    font-weight: 600;
    letter-spacing: .22em;
    text-transform: uppercase;
    color: #79A349;
}

.app-loading-env[hidden] { display: none; }

.app-loading-brand {
    font-size: 2.1rem;
    font-weight: 700;
    letter-spacing: .14em;
    animation: loading-pulse 1600ms ease-in-out infinite;
}

.app-loading-brand .accent { color: #79A349; }

.app-loading-sub {
    margin-top: .5rem;
    opacity: .7;
    font-size: .9rem;
}

@keyframes loading-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: .55; }
}

#blazor-error-ui {
    background: lightyellow;
    color: #3e2723;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }

/* ── Responsive collapse ──────────────────────────────────────────────── */

@media (max-width: 900px) {
    .hero {
        grid-template-columns: 1fr;
        padding-bottom: 56px;
        gap: 36px;
    }

    .flow-steps { grid-template-columns: repeat(2, 1fr); }

    .bento-grid { grid-template-columns: 1fr 1fr; }
    .bento-tile--proof { grid-column: span 2; }
    .bento-tile--screen { grid-row: span 1; }

    .field-inner { grid-template-columns: 1fr; gap: 32px; }

    .stat-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 560px) {
    .flow-steps { grid-template-columns: 1fr; }
    .bento-grid { grid-template-columns: 1fr; }
    .bento-tile--proof { grid-column: span 1; }
    .hero-ctas .btn-pill { width: 100%; }

    /* POC-U3: a single column stacked the four console tiles into a tall wall
       (the uptime tile ate a third of the screen). Keep a denser 2-up grid with
       smaller numerals and tighter padding instead. */
    .stat-grid { grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 16px; }
    .stat-tile { padding: 12px 14px; border-radius: 12px; }
    .stat-tile .stat-label { font-size: 0.68rem; margin-bottom: 3px; }
    .stat-tile .stat-value { font-size: 1.02rem; }
}

/* ── Console mobile repair (POC-U1/U3/U4 + nav pass) ──────────────────────── */

@media (max-width: 600px) {
    /* POC-U1: on phone widths every .t-tabs strip (the main strip AND the
       Pipelines / Infrastructure / ops sub-strips) is wider than the screen.
       The floating .t-tabs-pill assumes equal 1/tab-count columns resolved
       against the CONTAINER padding box, so once the grid overflows the pill's
       %-width/translate math breaks and it lands mid-tab. Fixing that math is
       fragile; instead we make selection correct BY CONSTRUCTION: drop the
       floating pill and paint the white pill look onto the selected button
       itself, so the indicator is always exactly on the clicked tab regardless
       of overflow. Each strip scrolls sideways (scrollbar hidden) with a fixed
       column floor so every column stays identical and labels stay legible. */
    .t-tabs {
        overflow-x: auto;
        scrollbar-width: none;
        grid-auto-columns: minmax(104px, 1fr);
        /* Discoverability (F3): a scroll-snap peek so a partial "next pill" shows there is more,
           plus a right-edge fade that signals the strip scrolls past the viewport. */
        scroll-snap-type: x proximity;
        -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent 100%);
        mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent 100%);
    }

    /* The fade must never clip a tab's focus ring (WP risk note) — lift it while any tab is focused. */
    .t-tabs:focus-within {
        -webkit-mask-image: none;
        mask-image: none;
    }

    .t-tabs::-webkit-scrollbar { display: none; }

    .t-tabs-pill { display: none; }

    /* The selected button now carries the pill background/shadow (matching the
       desktop floating pill: #fff, radius 999px from the base rule, soft navy
       shadow). Background/shadow transition too so the swap still feels
       animated; the reduced-motion block already kills all .t-tab transitions. */
    .t-tab {
        padding: 4px 10px;
        font-size: 0.8rem;
        scroll-snap-align: start;
        transition: color var(--tabs-dur) var(--tabs-ease),
                    background-color var(--tabs-dur) var(--tabs-ease),
                    box-shadow var(--tabs-dur) var(--tabs-ease);
    }

    .t-tab[aria-selected="true"] {
        background: var(--pill-surface);
        box-shadow: 0 1px 4px var(--pill-shadow);
    }

    /* POC-U3: intro prose clamps to one line behind the Show more/less toggle. */
    .intro-blurb > :first-child {
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 1;
        overflow: hidden;
    }

    .intro-blurb.is-expanded > :first-child {
        -webkit-line-clamp: unset;
        overflow: visible;
    }

    .intro-blurb-toggle {
        display: inline-block;
        border: 0;
        background: transparent;
        padding: 0 0 8px;
        color: var(--accent-green);
        font: 600 0.75rem 'Lexend Deca', sans-serif;
        cursor: pointer;
    }

    /* POC-U4: the info/error alerts render huge on a phone — same content, denser
       type and padding so the dual-mode sign-in note is a note, not a wall. */
    .mud-alert { padding: 6px 12px; }
    .mud-alert .mud-alert-message { font-size: 0.8rem; line-height: 1.45; }

    /* Nav pass: free app-bar room so the bell + avatar never crowd the brand —
       drop the decorative "Release console" subtitle (the logo carries context),
       let the page header wrap, and hide the redundant "Signed in as" (the app-bar
       avatar already shows who is signed in). */
    .brand-sub { display: none; }
    .console-head { flex-wrap: wrap; row-gap: 6px; }
    .console-head .signed-in-as { display: none; }

    /* F9: with the skew chip present the head crowded — force the title onto its own row so the
       env/feed/skew chips wrap together on the line below, and shrink the chip padding. */
    .console-head > h1 { flex-basis: 100%; }
    .console-head .feed-chip,
    .console-head .skew-chip { padding: 2px 8px; }

    /* Same nav pass: the version stamp leaves the crowded bar and re-surfaces inside
       the user menu (its entry + divider are display:none on desktop, above). */
    .navbar-version { display: none; }
    .user-menu-version { display: block; }
    .user-menu-version-divider { display: block; }
}

/* ── Live release feed chip ───────────────────────────────────────────── */

.feed-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border-radius: 999px;
    font: 600 0.68rem/1.4 'Lexend Deca', sans-serif;
    letter-spacing: 0.06em;
    border: 1px solid transparent;
}

.feed-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }

.feed-chip--live {
    color: var(--accent-green);
    border-color: var(--arro-green-leaf);
    background: rgba(121, 163, 73, 0.12);
}

.feed-chip--live .feed-dot { animation: feed-pulse 1.6s ease-in-out infinite; }

.feed-chip--connecting,
.feed-chip--reconnecting {
    color: var(--accent-blue);
    border-color: var(--arro-sky);
    background: rgba(25, 153, 204, 0.10);
}

.feed-chip--offline {
    color: var(--text-muted);
    border-color: var(--border-card);
    background: var(--surface-inset);
}

@keyframes feed-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(54, 134, 4, 0.45); }
    50% { box-shadow: 0 0 0 5px rgba(54, 134, 4, 0); }
}

/* ── Version-skew chip (Phase 14 WP2) ─────────────────────────────────── */
/* Amber "heads up, this bundle is behind the deployed API" — the SW update check has already been
   nudged (toast pending); reload catches up. Sits beside the feed chip in the console header. */
.skew-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border-radius: 999px;
    font: 600 0.68rem/1.4 'Lexend Deca', sans-serif;
    letter-spacing: 0.04em;
    color: #9A5B00;
    border: 1px solid #E7B85C;
    background: rgba(231, 184, 92, 0.14);
}

/* On the dark base the deep-amber text drops below AA — lift to the border amber. */
html.arro-dark .skew-chip {
    color: #F0C674;
    border-color: rgba(231, 184, 92, 0.55);
    background: rgba(231, 184, 92, 0.16);
}

.skew-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }

/* ── Feature-flags demo banner (0.0.9) ────────────────────────────────── */
/* Distinctive but on-theme: ARRO green wash over the outlined MudAlert. Appears/disappears as
   the 30s /api/features poll observes the demo-banner flag flip in Azure App Configuration. */
.demo-banner {
    border-color: var(--arro-green-leaf);
    background: rgba(121, 163, 73, 0.10);
}

/* ── Swap-in-flight latch (Phase 14 WP3) ──────────────────────────────── */
/* While two builds interleave during the swap warmup, the console latches into this deliberate
   "deployment in flight" card — outgoing (blue) → incoming (green) — instead of flapping tiles. */
.swap-inflight {
    border: 1px solid var(--arro-sky);
    border-radius: 16px;
    /* Blue→green wash over a themed base so the latch card seats on light AND dark. */
    background: linear-gradient(180deg, rgba(25, 153, 204, 0.06), rgba(121, 163, 73, 0.06)), var(--surface-card);
    padding: 16px 18px;
    margin-bottom: 20px;
}

.swap-inflight-head {
    display: flex;
    align-items: center;
    gap: 8px;
    font-weight: 700;
    color: var(--text-strong);
    margin-bottom: 14px;
}

.swap-inflight-head .feed-dot {
    color: var(--accent-blue);
    animation: feed-pulse 1.6s ease-in-out infinite;
}

.swap-builds {
    display: flex;
    align-items: stretch;
    gap: 14px;
    flex-wrap: wrap;
}

.swap-build {
    flex: 1 1 180px;
    background: var(--surface-card);
    border-radius: 12px;
    padding: 12px 14px;
    border: 1px solid var(--border-card);
}

.swap-build--out { border-left: 4px solid var(--accent-blue); }
.swap-build--in { border-left: 4px solid var(--accent-green); }

.swap-build-role {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
    margin-bottom: 4px;
}

.swap-build-num {
    font: 700 1.05rem/1.3 ui-monospace, Consolas, monospace;
    color: var(--text-strong);
    word-break: break-all;
}

.swap-build--out .swap-build-num { color: var(--accent-blue); }
.swap-build--in .swap-build-num { color: var(--accent-green); }

.swap-build-slot {
    font-size: 0.72rem;
    color: var(--text-muted);
    margin-top: 2px;
}

.swap-arrow {
    align-self: center;
    font-size: 1.4rem;
    font-weight: 700;
    /* Signature moment (research #3): while the swap is in flight the arrow flows blue→green,
       echoing outgoing→incoming. A marching background-position on clipped text — transform-free,
       reduced-motion collapses it back to a solid muted glyph below. */
    background: linear-gradient(90deg, var(--accent-blue) 0%, var(--accent-green) 50%, var(--accent-blue) 100%);
    background-size: 200% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
    animation: swap-arrow-flow 1.4s linear infinite;
}

@keyframes swap-arrow-flow {
    from { background-position: 200% 0; }
    to { background-position: 0 0; }
}

/* Build-number pop on the latch flip: the Build tile's value is @key'd on the build identity, so
   when the swap settles onto the new build the element remounts and replays this pop (t-digit idiom). */
.build-pop {
    display: inline-block;
    animation: build-pop 420ms var(--digit-ease) both;
}

@keyframes build-pop {
    0% { transform: translateY(var(--digit-distance)); opacity: 0; filter: blur(var(--digit-blur)); }
    100% { transform: translateY(0); opacity: 1; filter: blur(0); }
}

/* The incoming build number pops in when the in-flight panel latches (cross-fade partner of the
   outgoing side, which is already on screen). */
.swap-build--in .swap-build-num {
    animation: build-pop 420ms var(--digit-ease) both;
}

.swap-inflight-note {
    font-size: 0.78rem;
    color: var(--text-muted);
    margin-top: 12px;
    line-height: 1.5;
}

@media (max-width: 599px) {
    .swap-arrow { transform: rotate(90deg); }
}

/* ── Diagram figures (excalidraw artwork; docs/plans/wp-excalidraw-diagrams.md) ──
   The pipelines / team-flow / infrastructure diagrams are theme-aware images: the
   light + dark SVGs swap on prefers-color-scheme via <picture>, and the figure carries
   its own themed surface so a dark diagram reads on the console chrome. The doctrine that
   used to live on the clickable nodes moves into a collapsible <details> legend. */
.diagram-figure {
    margin: 0;
    border: 1px solid var(--border-card);
    border-radius: 14px;
    background: var(--diagram-frame);
    padding: 6px;
    overflow: hidden;
}

.diagram-img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: 10px;
    /* CLS fix (F4): reserve box space before the lazy-loaded SVG arrives so a sub-tab switch does
       not jump. The `auto` keyword yields to the SVG's own viewBox ratio once loaded (no distortion);
       3/2 is only the pre-load placeholder. */
    aspect-ratio: auto 3 / 2;
}

/* Theme-aware diagram swap (wp-poc-dark-mode): the APP theme — not only the OS —
   picks the variant, so the diagram always matches the console surface it sits on
   (System mode resolves to the OS scheme via the html class, so the old
   prefers-color-scheme behaviour still holds). html always carries a definite
   arro-light/arro-dark class, so this gating is exhaustive in every toggle state. */
.diagram-img--dark { display: none; }
html.arro-dark .diagram-img--light { display: none; }
html.arro-dark .diagram-img--dark { display: block; }

.diagram-figure-cap {
    margin: 8px 6px 2px;
    font: 400 0.75rem 'Lexend Deca', sans-serif;
    color: var(--text-muted);
}

.diagram-legend {
    margin: 6px;
    border-top: 1px solid var(--border-card);
    padding-top: 4px;
}

.diagram-legend > summary {
    cursor: pointer;
    font: 600 0.82rem 'Lexend Deca', sans-serif;
    color: var(--text-strong);
    padding: 6px 2px;
    list-style: none;
}

.diagram-legend > summary::-webkit-details-marker { display: none; }

.diagram-legend > summary::before {
    content: '\25B8';
    display: inline-block;
    margin-right: 8px;
    color: var(--arro-green);
    transition: transform 160ms ease;
}

.diagram-legend[open] > summary::before { transform: rotate(90deg); }

.diagram-legend > summary:focus-visible {
    outline: 2px solid var(--arro-green-dark);
    outline-offset: 2px;
    border-radius: 6px;
}

.diagram-legend-body {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 10px 22px;
    padding: 8px 2px 4px;
}

.diagram-legend-body section { margin: 0; }

.diagram-legend-body h5 {
    margin: 0 0 3px;
    font: 700 0.8rem 'Lexend Deca', sans-serif;
    color: var(--text-strong);
}

.diagram-legend-body p {
    margin: 0;
    font: 400 0.78rem 'Lexend Deca', sans-serif;
    color: var(--text-muted);
    line-height: 1.5;
}

.diagram-legend-body code {
    font-size: 0.92em;
    background: var(--diagram-code-bg);
    padding: 0 4px;
    border-radius: 4px;
    color: var(--text-strong);
}

/* NB: the former @media (prefers-color-scheme: dark) diagram overrides are gone —
   the figure chrome now reads the theme tokens above, so it follows the APP theme
   (System/Light/Dark) in lockstep with the image variant instead of only the OS. */

@media (prefers-reduced-motion: reduce) {
    .diagram-legend > summary::before { transition: none; }
}


/* ── PWA update toast ─────────────────────────────────────────────────── */

.pwa-toast {
    position: fixed;
    left: 50%;
    /* Pin clear of the footer / last table rows and above any device safe-area (UX #11): the toast
       floats over the reserved bottom padding on .mud-main-content below, not on top of content. */
    bottom: calc(24px + env(safe-area-inset-bottom, 0px));
    transform: translateX(-50%);
    z-index: 2000;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px 10px 18px;
    background: var(--arro-navy);
    color: rgba(255, 255, 255, 0.92);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 999px;
    box-shadow: 0 12px 32px rgba(4, 45, 73, 0.35);
    font-family: 'Lexend Deca', sans-serif;
    font-size: 0.85rem;
    white-space: nowrap;
}

.pwa-toast-update {
    border: 0;
    border-radius: 999px;
    padding: 7px 16px;
    background: var(--arro-green, #79A349);
    color: #ffffff;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}

.pwa-toast-update:hover { filter: brightness(1.08); }

/* Mid-apply ("Updating…") — visibly busy, not clickable, never hover-brightened. */
.pwa-toast-update:disabled { opacity: 0.7; cursor: default; filter: none; }

.pwa-toast-dismiss {
    border: 0;
    background: transparent;
    color: rgba(255, 255, 255, 0.55);
    font-size: 0.8rem;
    cursor: pointer;
    padding: 4px 6px;
}

.pwa-toast-dismiss:hover { color: #ffffff; }

/* Reserve bottom room on the app content so the fixed update toast never lands on the last table
   rows / footer caption (UX #11). Scoped to MudMainContent — the landing page uses its own layout. */
.mud-main-content { padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px)); }

/* ── Skeleton loading (skeletons over spinners — SkeletonBoundary et al) ── */

/* Content mounting in place of a skeleton enters with the transitions.dev
   skeleton-reveal fade + un-blur; the skeleton itself pulses via MudSkeleton
   (light surfaces) or .skel-line (dark surfaces, where MudBlazor's dark-on-light
   wash is invisible). */
.skel-reveal {
    animation: skel-reveal var(--skel-reveal-dur) var(--skel-reveal-ease) both;
}

@keyframes skel-reveal {
    from { opacity: 0; filter: blur(var(--skel-reveal-blur)); }
    to { opacity: 1; filter: blur(0); }
}

.skel-code {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin: 16px 0 0;
    padding: 14px 16px;
    background: rgba(255, 255, 255, 0.07);
    border-radius: 10px;
}

.skel-line {
    height: 12px;
    border-radius: 6px;
    background: rgba(255, 255, 255, 0.16);
    animation: skel-pulse var(--skel-pulse-dur) ease-in-out infinite;
}

@keyframes skel-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: .45; }
}

/* ── Reduced motion: collapse everything to static ────────────────────── */

@media (prefers-reduced-motion: reduce) {
    .t-stagger-line,
    .reveal,
    .t-tabs-pill,
    .t-tab,
    .t-input,
    .btn-pill { transition: none !important; }

    .t-stagger-line,
    .reveal {
        opacity: 1;
        transform: none;
        filter: none;
    }

    .t-tilt-card { transform: none !important; transition: none !important; }
    .t-digit-group .t-digit { animation: none !important; }
    .t-input.is-shaking { animation: none !important; }
    .panel-enter { animation: none !important; }
    .app-loading-brand { animation: none !important; }
    .app-loading-icon { animation: none !important; }
    .skel-reveal { animation: none !important; }
    .skel-line { animation: none !important; }
    .shimmer-text { animation: none !important; color: #555; }

    .t-success-check { animation: none !important; opacity: 1; }
    .t-success-check svg path { animation: none !important; stroke-dashoffset: 0 !important; }

    .feed-chip--live .feed-dot { animation: none !important; }

    /* Theme change is instant — no rotate/fade sweep on the toggle icon. */
    .theme-toggle-icon { animation: none !important; }
    .theme-toggle { transition: none !important; }

    /* wp-poc-demo-polish signature moments collapse to static. */
    .build-pop,
    .swap-build--in .swap-build-num { animation: none !important; transform: none; opacity: 1; filter: none; }
    .message-badge .mud-badge { animation: none !important; scale: 1; }

    /* The in-flight arrow stops flowing AND restores a solid glyph (undo the clipped-text gradient). */
    .swap-arrow {
        animation: none !important;
        background: none !important;
        color: var(--text-muted) !important;
        -webkit-text-fill-color: var(--text-muted) !important;
        -webkit-background-clip: border-box !important;
        background-clip: border-box !important;
    }

    .skip-link { transition: none !important; }
}

/* ── Message center + admin (Phase 9c) ──────────────────────────────────── */

.message-bell { color: #fff; }

/* Signature moment (F10): the unread badge pops when it (re)appears on a new message. The MudBadge
   host is @key'd on the unread count, so each increment remounts the bubble and replays this. The
   independent `scale` property is used (NOT transform) so MudBadge's own overlap translate survives. */
.message-badge .mud-badge {
    transform-origin: center;
    animation: badge-pop 360ms var(--digit-ease) both;
}

@keyframes badge-pop {
    0% { scale: 0; }
    60% { scale: 1.25; }
    100% { scale: 1; }
}

.message-center-popover { z-index: 1600; }

.message-center-overlay {
    position: fixed;
    inset: 0;
    z-index: 1500;
    background: transparent;
}

.message-center-panel {
    width: 340px;
    max-width: 90vw;
}

.message-center-head {
    display: flex;
    align-items: center;
    padding: 8px 8px 8px 16px;
}

.message-list { max-height: 60vh; overflow-y: auto; }

.message-item {
    padding: 10px 16px;
    border-left: 3px solid transparent;
    border-bottom: 1px solid var(--border-card);
}

.message-item--release { border-left-color: var(--arro-green); background: rgba(121, 163, 73, 0.08); }

.message-item--admin { border-left-color: var(--arro-sky); }

.message-item-head {
    display: flex;
    align-items: center;
    gap: 6px;
    color: var(--text-strong);
}

.message-item-title { font: 600 0.85rem/1.3 'Lexend Deca', sans-serif; flex: 1; }

.message-item-time { font-size: 0.7rem; color: var(--text-muted); }

.message-item-body {
    margin-top: 4px;
    font-size: 0.8rem;
    color: var(--text-muted);
    padding-left: 22px;
}

/* ── Web push toggle (Phase 9d) ───────────────────────────────────────────── */

.push-toggle {
    display: flex;
    flex-direction: column;
    padding: 10px 16px 12px;
    gap: 2px;
}

.push-toggle-head {
    display: flex;
    align-items: center;
    gap: 6px;
    font-weight: 700;
    font-size: 0.8rem;
}

.push-toggle-icon {
    color: var(--accent-green);
}

.push-toggle-title {
    letter-spacing: 0.01em;
}

.push-state {
    font-size: 0.72rem;
    color: var(--text-muted);
    padding-left: 2px;
}

/* Anonymous landing opt-in: a restrained inline block under the footer nav. */
.landing-footer .footer-push {
    margin-top: 10px;
    display: flex;
    justify-content: center;
}

.landing-footer .footer-push .push-toggle {
    padding: 8px 14px;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.06);
    max-width: 320px;
}

.landing-footer .footer-push .push-toggle-title {
    color: rgba(255, 255, 255, 0.9);
}

.landing-footer .footer-push .push-state {
    color: rgba(255, 255, 255, 0.6);
}

