/*
 * TaiGHT Global Styles — Nordic Precision
 */

*,
*::before,
*::after {
    box-sizing: border-box;
}

html, body {
    height: 100%;
    margin: 0;
    padding: 0;
    font-family: var(--mud-typography-default-family, 'Space Grotesk', system-ui, sans-serif);
    font-size: var(--mud-typography-default-size, 1rem);
    line-height: var(--mud-typography-default-lineheight, 1.6);
    background-color: var(--mud-palette-background, var(--brand-bg));
    color: var(--mud-palette-text-primary, var(--brand-text-primary));
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

h1:focus { outline: none; }

/* Blazor error boundary */
.blazor-error-boundary {
    background-color: var(--mud-palette-error);
    padding: 1rem;
    color: #fff;
}

.blazor-error-boundary::after {
    content: "An error has occurred.";
}

/* ============================================
   HERO
   ============================================ */
.hero-section {
    position: relative;
    background: var(--gradient-cosmic-cosmos);
    color: var(--mud-palette-appbar-text);
    overflow: hidden;
}

/* Cosmic starfield wrapper. Fills the hero band, sits behind the content
   (the hero's MudContainer carries position: relative + z-index: 1). The
   two canvases stack on top of each other; Layer 2 (Three.js drifting
   points) paints over Layer 1 (static field with blinkers). Both
   pointer-events: none so they never intercept clicks on the hero. */
.starfield {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 0;
}
.starfield canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
}

/* Signature wire icosahedron — Three.js scene host. Lives inside the home
   hero, beneath the CTA stack. Background is transparent so the hero's
   cosmic gradient + starfield show through. Hidden on mobile (the JS init
   short-circuits there as well, so no WebGL context is created). */
.icosahedron-band {
    position: relative;
    width: 100%;
    max-width: 520px;
    height: 340px;
    margin: 0 auto;
    background: transparent;
    overflow: visible;
}
.icosahedron-band canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
}
@media (max-width: 768px) {
    .icosahedron-band { display: none; }
    /* Icosahedron is the hero's bottom spacer on desktop -- hiding it on
       mobile leaves the CTAs hugging the next section, so restore the 64
       px bottom pad that the hero's pt-16 only puts on top. */
    .hero-section .mud-grid {
        padding-bottom: 64px;
    }
}

/* Hero logo above the display title (replaces the old "Earth-based" pill) */
.hero-logo {
    width: clamp(120px, 14vw, 180px);
    height: auto;
    display: block;
}

/* ============================================
   SECTIONS
   ============================================ */
.section-alt {
    background-color: var(--mud-palette-surface);
}

.section-dark {
    background: var(--mud-palette-secondary);
    color: var(--mud-palette-appbar-text);
}

.section-accent {
    background: var(--gradient-cosmic-cosmos);
    color: var(--brand-almost-white);
}

/* ============================================
   SERVICE CARDS
   ============================================ */
.service-card-icon {
    font-size: var(--typo-headline-2-size) !important;
    width: var(--typo-headline-2-size) !important;
    height: var(--typo-headline-2-size) !important;
    color: var(--brand-aqua-pulse) !important;
    align-self: flex-start;
}

/* ============================================
   SUBTLE EFFECTS
   ============================================ */
.glass-card {
    background: color-mix(in srgb, var(--brand-night-violet) 50%, transparent);
    backdrop-filter: blur(12px);
    border: 1px solid color-mix(in srgb, var(--brand-nebula-violet) 30%, transparent);
}

.hover-lift {
    transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.hover-lift:hover {
    transform: translateY(-6px);
    box-shadow: 0 20px 40px color-mix(in srgb, var(--brand-nebula-violet) 25%, transparent);
}

/* Brand button variants (per design PDF #5).
   - .btn-primary   = Filled Nebula Violet + Almost White text — the Main CTA
   - .btn-secondary = transparent + Almost White border + Almost White text
   - .btn-tertiary  = text-only, Almost White (defined further down)
   Pair with MudButton Variant="Variant.Filled" / "Variant.Outlined" /
   "Variant.Text" respectively. */
.btn-primary {
    background: var(--brand-nebula-violet) !important;
    color: var(--brand-almost-white) !important;
}
.btn-primary:hover {
    background: var(--brand-galaxy-purple) !important;
}

.btn-secondary {
    border: 1px solid var(--brand-nebula-violet) !important;
    color: var(--brand-almost-white) !important;
    background: transparent !important;
}
.btn-secondary:hover {
    background: color-mix(in srgb, var(--brand-nebula-violet) 15%, transparent) !important;
    border-color: var(--brand-nebula-violet) !important;
}

/* TaiGHT brand — highlight "ai" */
.brand-ai {
    color: var(--brand-aqua-pulse);
    font-style: normal;
}

/* Article body — rendered markdown */
.article-body h2 {
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    margin-top: 2.5rem;
    margin-bottom: 0.75rem;
    color: var(--mud-palette-text-primary);
}

.article-body h3 {
    font-size: 1.25rem;
    font-weight: 600;
    margin-top: 2rem;
    margin-bottom: 0.5rem;
    color: var(--mud-palette-text-primary);
}

.article-body p {
    color: var(--mud-palette-text-secondary);
    line-height: var(--line-height-article);
    margin-bottom: 1rem;
}

.article-body strong {
    color: var(--brand-aqua-pulse);
    font-weight: 600;
}

/* Long-form paragraph utility — applies the prose line-height
   to brand Body (16px) without changing the font size. Use on
   non-card narrative copy (Privacy paragraphs, About body, etc.)
   where the tight 20px brand line feels cramped.
   Multiple selectors handle plain HTML (<ul>, <p>) and MudText's
   compound class output (.mud-typography.body-prose). */
.body-prose,
.mud-typography.body-prose,
ul.body-prose,
p.body-prose {
    line-height: var(--line-height-prose) !important;
}

.article-body table {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 1.5rem;
    font-size: 0.9rem;
}

.article-body ul,
.article-body ol {
    color: var(--mud-palette-text-secondary);
    line-height: var(--line-height-article);
    margin-bottom: 1rem;
    padding-left: 2rem;
}

/* Aqua Pulse bullets / numbers in article lists. */
.article-body li::marker {
    color: var(--brand-aqua-pulse);
}

.article-body th {
    text-align: left;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
    padding: 10px 12px;
    border-bottom: 2px solid var(--mud-palette-divider);
    background: var(--mud-palette-surface);
}

.article-body td {
    padding: 8px 12px;
    border-bottom: 1px solid var(--mud-palette-divider);
    color: var(--mud-palette-text-secondary);
    line-height: 1.6;
}

.article-body tr:hover td {
    background: var(--mud-palette-primary-hover);
}

.article-body li {
    margin-bottom: 0.4rem;
}

.article-body blockquote {
    border-left: 3px solid var(--mud-palette-primary);
    padding-left: 1rem;
    margin: 1.5rem 0;
    color: var(--mud-palette-text-secondary);
    font-style: italic;
}

.article-body code {
    background: var(--mud-palette-surface);
    padding: 0.15rem 0.4rem;
    border-radius: 4px;
    font-size: 0.9em;
}

.article-body pre {
    background: var(--mud-palette-surface);
    padding: 1rem;
    border-radius: var(--mud-default-borderradius);
    overflow-x: auto;
    margin-bottom: 1rem;
}

/* Markdown body images */
.article-body img {
    max-width: 100%;
    height: auto;
    border-radius: var(--mud-default-borderradius);
    display: block;
    margin: 1em 0;
}

/* Article 3-column layout: TOC | Article | Sidebar */
.article-3col {
    display: grid;
    grid-template-columns: 180px 1fr 240px;
    gap: 2rem;
}

.article-toc-inner {
    position: sticky;
    top: var(--site-sticky-top);
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 16px;
    border: 1px solid var(--mud-palette-divider);
    border-radius: var(--mud-default-borderradius);
    background: var(--mud-palette-surface);
}

.article-main {
    min-width: 0;
}

.article-sidebar-sticky {
    position: sticky;
    top: 80px;
}

.toc-item {
    font-size: 0.75rem;
    color: var(--brand-almost-white);
    text-decoration: none;
    padding: 4px 0 4px 12px;
    border-left: 2px solid var(--mud-palette-divider);
    line-height: 1.4;
    transition: color 0.2s, border-color 0.2s;
    cursor: pointer;
}

.toc-item:hover,
.toc-item.toc-active {
    color: var(--brand-neo-turquoise);
    border-left-color: var(--brand-neo-turquoise);
}

.toc-cta {
    margin-top: 8px;
    font-weight: 600;
    color: var(--mud-palette-primary);
    border-left-color: var(--mud-palette-primary);
    border-left-width: 3px;
    opacity: 1;
    animation: toc-glow 3s ease-in-out infinite;
}

@keyframes toc-glow {
    0%, 100% { color: var(--mud-palette-primary); text-shadow: 0 0 4px color-mix(in srgb, var(--brand-nebula-violet) 25%, transparent); }
    50% { color: var(--brand-plasma-pink); text-shadow: 0 0 16px color-mix(in srgb, var(--brand-plasma-pink) 60%, transparent); }
}

/* Medium: 2 columns, TOC moves to right sidebar position */
@media (max-width: 1200px) {
    .article-3col {
        grid-template-columns: 1fr 180px;
    }

    .article-toc {
        order: 2;
        grid-column: 2;
        grid-row: 1 / -1;
    }

    .article-main {
        grid-column: 1;
    }

    .article-sidebar {
        grid-column: 1;
        order: 3;
    }

    .article-sidebar-sticky {
        position: static;
    }
}

/* Mobile: 1 column, sidebar below, desktop TOC hidden in favour of the
   FAB + bottom-sheet drawer. */
@media (max-width: 768px) {
    .article-3col {
        grid-template-columns: 1fr;
    }

    .article-toc {
        display: none;
    }

    .article-main {
        grid-column: 1;
        grid-row: auto;
    }

    .article-sidebar {
        grid-column: 1;
    }
}

/* Site footer. Pinned to the viewport bottom as a semantic <footer>.
   Z-index 100 sits below MudBlazor's reserved layers (drawer 1100,
   popover 1200, appbar 1300, dialog 1400) so floating UI like the
   article-toc FAB can layer cleanly above. */
.site-footer {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 100;
    height: 48px;
    padding: 0 16px;
    display: flex;
    align-items: center;
    background-color: var(--brand-cosmic-black);
    color: var(--brand-almost-white);
}
.site-footer-spacer {
    flex: 1 1 auto;
}

/* Article TOC FAB (mobile only). Centred horizontally with its centre on
   the footer's top edge: footer height is 48px, FAB medium is 48px, so
   bottom = 48 - 24 = 24px puts the FAB centre exactly on the footer's top
   edge. Z-index 200 sits above the site footer (100) but well below
   MudBlazor's drawer layer (1100) so the bottom-sheet drawer covers the
   FAB when open. */
.article-toc-fab {
    display: none;
}
@media (max-width: 768px) {
    .article-toc-fab {
        display: inline-flex;
        position: fixed;
        left: 50%;
        bottom: calc(24px + env(safe-area-inset-bottom));
        transform: translateX(-50%);
        z-index: 200;
    }
}

/* Bottom-sheet drawer that hosts the heading list on mobile. Capped at 60vh
   so the article stays partially visible behind the scrim — the user keeps
   their place. Hidden via the FAB media query on desktop / tablet. */
.article-toc-drawer {
    max-height: 60vh;
}
.article-toc-drawer .toc-item {
    padding: 12px 8px;
    font-size: 16px;
}

/* Smooth scroll for anchor links */
html {
    scroll-behavior: smooth;
    scroll-padding-top: 80px;
}

/* Showcase dimension descriptions — line-clamp for consistent height */
.dim-desc {
    display: -webkit-box;
    -webkit-line-clamp: 5;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.dim-desc-expanded {
    -webkit-line-clamp: unset;
    overflow: visible;
}

/* MudBlazor popover z-index is handled by the framework:
   calc(var(--mud-zindex-dialog) + 3) — already above dialogs.
   Do NOT override with a hardcoded value or popovers inside
   dialogs will render behind the dialog overlay. */

/* Select group headers — override disabled grey */
.mud-list-item.select-group-header,
.mud-list-item.select-group-header .mud-list-item-text,
.mud-list-item.select-group-header .mud-list-item-text * {
    font-size: 0.7rem !important;
    font-weight: 700 !important;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    opacity: 1 !important;
    color: var(--mud-palette-primary) !important;
}

.mud-list-item.select-group-header {
    padding-top: 12px;
    padding-bottom: 2px;
    min-height: 28px;
    pointer-events: none;
}

.select-group-item {
    padding-left: 24px;
}

/* === Floating surface contrast ===
   Dialogs, popovers (select/datepicker/autocomplete/menu dropdowns),
   and the cookie consent banner default to Surface (#11041F Midnight
   Violet) which collides with the page background, leaving floating
   elements with no visible edge. Lift them one tier to Deep Cosmos
   and add a Plasma Pink hairline so edges register clearly.

   Snackbars are intentionally excluded — their severity colour
   (success/warning/error) carries the meaning. */
.mud-dialog,
.mud-popover,
.cosmic-floating {
    background-color: var(--brand-deep-cosmos) !important;
    border: 1px solid var(--brand-plasma-pink) !important;
}

/* === Input accent ===
   Focus + hover states use Aqua Pulse instead of Nebula Violet (Nebula
   is reserved for buttons; inputs follow the cosmic accent pattern —
   aqua icons, aqua hover/focus states).

   MudBlazor uses :focus-within (pseudo-class) for focus, NOT a
   .mud-focused class, and the floating label is a sibling of .mud-input
   via ~ — see _input.scss / _inputlabel.scss for the source rules these
   override. */

/* Input text size -> brand Body (16px), not Intro (21px).
   MudBlazor sizes every input and its floating label from the Subtitle1
   typography slot, which our theme uses for the brand Intro style. At
   21px, values truncate in narrow fields and the shrunk label (0.75 x
   21) is wider than the outline notch MudBlazor cuts for a 12px label,
   so the label crosses the border. Selectors match MudBlazor's own
   (_input.scss / _inputlabel.scss) with higher specificity. */
.mud-input.mud-typography-subtitle1,
.mud-input-control > .mud-input-control-input-container > .mud-input-label.mud-input-label-inputcontrol {
    font-size: var(--typo-body-size);
}

/* Focused outlined border -> Aqua Pulse */
.mud-input.mud-input-outlined:focus-within > .mud-input-outlined-border {
    border-color: var(--brand-aqua-pulse) !important;
}

/* Hover outlined border (not focused, not disabled) -> Aqua Pulse.
   Default MudBlazor hover uses --mud-palette-action-default which
   resolves to the light alloy / white-ish text colour. */
.mud-input.mud-input-outlined:not(.mud-disabled):not(:focus-within):hover > .mud-input-outlined-border {
    border-color: var(--brand-aqua-pulse) !important;
}

/* Floating label sitting on top of the outlined border -> Almost White,
   regardless of focus state. The Aqua Pulse accent lives on the
   outline border itself; the label is a quiet white sticker either way.
   Covers both shrunk (has value) and focused (cursor in field). */
.mud-input.mud-shrink ~ label.mud-input-label.mud-input-label-inputcontrol,
.mud-input:focus-within ~ label.mud-input-label.mud-input-label-inputcontrol {
    color: var(--brand-almost-white) !important;
}

/* Cookie consent banner */
.cookie-consent {
    position: fixed;
    bottom: 64px;
    left: 0;
    right: 0;
    z-index: 1500;
    display: flex;
    justify-content: center;
    padding: 0 16px;
    pointer-events: none;
}

.cookie-consent > * {
    pointer-events: auto;
}

/* Divider accent */
.section-divider {
    width: 48px;
    height: 3px;
    border-radius: 2px;
    background: var(--brand-plasma-pink);
}

/* Compact tag chip — Aqua Pulse outline, Almost White text.
   Used for content categorization (tech tags, etc.). */
.chip-tag {
    height: 22px !important;
    font-size: 0.65rem !important;
    border-color: var(--brand-aqua-pulse) !important;
    color: var(--brand-almost-white) !important;
}


/* MudToggleGroup — active item uses Nebula Violet fill + Almost White
   text, matching the brand button treatment. Inactive items inherit
   the Plasma Pink border from --mud-palette-lines-default. */
.mud-toggle-item.mud-toggle-item-selected {
    background-color: var(--brand-nebula-violet) !important;
    color: var(--brand-almost-white) !important;
}

/* Filter chip — interactive tag selector. Mirrors .chip-tag styling
   so unselected filters read consistently with content tags; the
   selected (Filled) variant inverts to aqua fill + cosmic-black text
   so it pops as the active state. */
.chip-filter {
    height: 28px !important;
    font-size: 0.75rem !important;
    border-color: var(--brand-aqua-pulse) !important;
    color: var(--brand-almost-white) !important;
}
.chip-filter.mud-chip-filled {
    background-color: var(--brand-aqua-pulse) !important;
    color: var(--brand-cosmic-black) !important;
    border-color: var(--brand-aqua-pulse) !important;
}

/* Tighten default MudChip margin inside tag containers */
.tag-chips .mud-chip {
    margin: 4px !important;
}

/* Markdown editor */
.md-editor-panes {
    display: flex;
    align-items: stretch;
}

.md-editor-edit {
    display: flex;
    flex-direction: column;
}

.md-editor-textarea {
    width: 100%;
    border: none;
    outline: none;
    resize: none;
    padding: 12px;
    font-family: 'Cascadia Code', 'Fira Code', monospace;
    font-size: 0.875rem;
    line-height: 1.5;
    background: transparent;
    color: var(--mud-palette-text-primary);
    flex: 1;
    field-sizing: content;
}

.md-editor-preview {
    overflow-y: auto;
}


/* ============================================
   COSMIC UTILITIES (issue #107)
   ============================================ */

/* Stat row — 5 equal columns with 18px gap. Drops to 3 then 2 cols
   on narrower viewports. Pure CSS Grid so every tile stays the same
   width without nested MudGrid+MudTooltip wrappers. */
.cosmic-stat-row {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 18px;
}
@media (max-width: 1024px) {
    .cosmic-stat-row { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 600px) {
    .cosmic-stat-row { grid-template-columns: repeat(2, 1fr); }
}

/* Stat tile — small non-clickable card with Aqua Pulse outline.
   Transparent fill so the section gradient shows through. Aspect
   ratio 10:8.5 matches the landing-page mockup. */
.cosmic-stat-tile {
    background: transparent;
    border: 1px solid var(--brand-aqua-pulse);
    border-radius: var(--mud-default-borderradius);
    padding: 0.75rem;
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    aspect-ratio: 10 / 8.5;
}
.cosmic-stat-tile__value {
    font-family: var(--brand-font);
    font-weight: 700;
    font-size: var(--typo-headline-2-size);
    line-height: var(--typo-headline-2-line);
    letter-spacing: -0.02em;
    color: var(--brand-aqua-pulse);
}
.cosmic-stat-tile__icon {
    font-size: var(--typo-headline-2-size) !important;
    color: var(--brand-aqua-pulse) !important;
    line-height: 1;
}
/* Stat tile label is a small UI-component caption — sized below the
   brand Body spec because the brand has no caption tier defined.
   Documented project-level extension: 12/16/500 uppercase. */
.cosmic-stat-tile__label {
    font-size: 12px;
    line-height: 16px;
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--brand-light-alloy);
}

/* Mobile nav-drawer link override. The TaiGHTTheme sets Button.TextTransform
   to "none" globally so MudButton labels render in proper case. The drawer
   wants the classic uppercase nav look for hierarchy + brand emphasis on
   mobile, so force it back on for these specific links. */
.drawer-nav-link {
    text-transform: uppercase !important;
    letter-spacing: 0.08em;
}

/* Section variant: matches the hero gradient. Use on a SectionContainer
   that needs visual continuity with the hero (e.g. the stats row). */
.section-hero-gradient {
    background: var(--gradient-cosmic-cosmos);
}

/* Service / showcase / poc / insight card — Midnight Violet surface
   with Plasma Pink accent outline. Use anywhere a content tile sits
   on the Cosmic Black page background.
   overflow:hidden makes child <img> respect the rounded corners. */
.cosmic-card {
    background: var(--brand-midnight-violet);
    border: 1px solid var(--brand-plasma-pink);
    border-radius: var(--mud-default-borderradius);
    overflow: hidden;
    transition: transform 250ms ease, border-color 250ms ease, box-shadow 250ms ease;
}
.cosmic-card:hover {
    transform: translateY(-4px);
    border-color: var(--brand-aqua-pulse);
    box-shadow: 0 12px 32px color-mix(in srgb, var(--brand-plasma-pink) 30%, transparent);
}
/* Opt-out modifier: cards used as static display containers (info
   panels, contact details, sidebars) shouldn't lift on hover.
   Apply with Class="cosmic-card cosmic-card--static" */
.cosmic-card--static {
    transition: none;
}
.cosmic-card--static:hover {
    transform: none;
    border-color: var(--brand-plasma-pink);
    box-shadow: none;
}

/* Card row — 3 equal columns with 18px gap, drops to 2 cols then 1
   on narrower viewports. Use for service / PoC / showcase / insight
   card sections. Replaces MudGrid+MudItem nesting. */
.cosmic-card-row {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 18px;
}
@media (max-width: 1024px) {
    .cosmic-card-row { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 720px) {
    .cosmic-card-row { grid-template-columns: 1fr; }
}

/* Brand accent colors — wrap any letter run in a span to highlight it.
   Use case: "Br<span class="accent-plasma">ai</span>npower". The
   wordmark "Taight" uses .brand-ai which is aqua; these are for
   broader copy accents. */
.accent-aqua    { color: var(--brand-aqua-pulse); }
.accent-plasma  { color: var(--brand-plasma-pink); }
.accent-turquoise { color: var(--brand-neo-turquoise); }
.accent-violet  { color: var(--brand-nebula-violet); }

/* Text links — site-wide Almost White text. Hover shifts to Neo
   Turquoise with an underline. Targets MudLink and raw <a> in
   article bodies. Excludes MudButton / MudIconButton / MudNavLink
   (they render <a> with their own classes). */
.mud-link,
.article-body a {
    color: var(--brand-almost-white) !important;
    text-decoration: none !important;
}
.mud-link:hover,
.article-body a:hover {
    color: var(--brand-neo-turquoise) !important;
    text-decoration: underline !important;
    text-decoration-color: var(--brand-neo-turquoise) !important;
    text-underline-offset: 0.2em !important;
    text-decoration-thickness: 2px !important;
}

/* EPPO PPP Showcase isolation — restores the original "Nordic Precision"
   palette inside this single subtree so the data-viz-heavy showcase
   keeps its intended light-theme aesthetic instead of inheriting
   Cosmic. Wrap the showcase content in <div class="eppo-isolate">. */
.eppo-isolate {
    --mud-palette-primary: #1E40AF;
    --mud-palette-secondary: #0F172A;
    --mud-palette-tertiary: #6366F1;
    --mud-palette-info: #1E40AF;
    --mud-palette-success: #059669;
    --mud-palette-warning: #D97706;
    --mud-palette-error: #DC2626;
    --mud-palette-background: #F8F7F4;
    --mud-palette-surface: #FFFFFF;
    --mud-palette-text-primary: #0F172A;
    --mud-palette-text-secondary: #64748B;
    --mud-palette-text-disabled: #94A3B8;
    --mud-palette-divider: #E2E8F0;
    --mud-palette-lines-default: #334155;
    --mud-palette-action-default: #64748B;

    background: #F8F7F4;
    color: #0F172A;
}
/* Hero stays Cosmic-themed even though the body of the showcase is
   isolated to the old light palette. Re-establish the dark text vars
   so MudText inside the hero reads white on the gradient. */
.eppo-isolate .hero-section {
    --mud-palette-text-primary: #F7F7F7;
    --mud-palette-text-secondary: #DBDBDB;
    background: var(--gradient-cosmic-cosmos);
    color: var(--brand-almost-white);
}
.eppo-isolate .mud-link,
.eppo-isolate .article-body a {
    color: #1E40AF !important;
    text-decoration: underline !important;
    text-decoration-color: #1E40AF !important;
}
.eppo-isolate .mud-link:hover,
.eppo-isolate .article-body a:hover {
    color: #1E40AF !important;
    text-decoration-color: #1E40AF !important;
    opacity: 0.8;
}

/* MudTable / MudSimpleTable inside a .cosmic-card use Plasma Pink cell
   borders to match the surrounding card outline. Force all sides via
   border-color so the rule wins regardless of which side MudBlazor
   actually paints (MudTable uses border-bottom on rows; MudSimpleTable
   uses different selectors). */
.cosmic-card .mud-table-cell,
.cosmic-card .mud-table-row .mud-table-cell,
.cosmic-card .mud-simple-table th,
.cosmic-card .mud-simple-table td,
.cosmic-card table th,
.cosmic-card table td {
    border-color: var(--brand-plasma-pink) !important;
}
.cosmic-card .mud-table-head .mud-table-cell,
.cosmic-card .mud-simple-table thead th {
    border-bottom-color: var(--brand-plasma-pink) !important;
}

/* Progress bar variant for "needs improvement" / low-score signals.
   Overrides the rendered MudProgressLinear bar fill so the color is
   driven by --brand-accent-improve (defined in theme.css). Apply
   Class="progress-improve" on the MudProgressLinear. */
.progress-improve .mud-progress-linear-bar,
.progress-improve.mud-progress-linear .mud-progress-linear-bar {
    background-color: var(--brand-accent-improve) !important;
}

/* Tertiary button — text-only, Almost White (PDF #5 Tertiary spec).
   Apply to MudButton Variant="Variant.Text" inside cards / lists. */
.btn-tertiary {
    color: var(--brand-almost-white) !important;
}
.btn-tertiary:hover {
    background: color-mix(in srgb, var(--brand-almost-white) 10%, transparent) !important;
}

/* ROI Calculator brand block — print-only (lives inside .roi-print-header).
   Centred horizontally above the title strip, sized to read as a strong
   masthead element on A4. Logo and wordmark in Almost White on screen
   (unused since the block is print-only), with "ai" letters picking up
   Aqua Pulse via the existing .brand-ai class. */
.roi-hero-brand {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}
.roi-hero-logo {
    width: 112px;
    height: auto;
}
.roi-hero-wordmark {
    font-family: var(--brand-font);
    font-size: 72px;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--brand-almost-white);
    line-height: 1;
}

/* ROI Calculator showcase. Sliders use tabular-nums values, scenario buttons
   highlight the active option in Aqua Pulse, and the "How we calculated this"
   formula list uses tighter typography for legibility on a long methodology
   disclosure. Print stylesheet hides the back-button, scenario toolbar, and
   share/reset/print buttons so a cleanly-printed summary survives. */
.roi-slider-row {
    margin-bottom: 4px;
}
.scenario-active {
    background-color: color-mix(in srgb, var(--brand-aqua-pulse) 12%, transparent) !important;
    border-color: var(--brand-aqua-pulse) !important;
    color: var(--brand-aqua-pulse) !important;
}
.roi-formula-list {
    margin: 0.5rem 0 0 1.25rem;
    padding: 0;
    line-height: 1.6;
    font-size: 0.875rem;
    /* Belt-and-braces: explicit brand font on the list since <li> inherits
       only via the global body rule, not via any MudBlazor typography class. */
    font-family: var(--brand-font);
}
.roi-formula-list li {
    margin-bottom: 0.4rem;
}
/* Sensitivity row: long input labels wrap freely on narrow widths,
   the money value stays on one line and right-aligns. */
.roi-sensitivity-row {
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    line-height: 1.3;
}
.roi-sensitivity-label {
    flex: 1 1 auto;
    min-width: 0;
    word-break: normal;
    overflow-wrap: anywhere;
}
.roi-sensitivity-value {
    flex: 0 0 auto;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-secondary);
}
/* Print-only header on the ROI Calculator. Hidden on screen, shown in
   print so the page identifies itself (title, scenario, URL, date). */
.roi-print-header {
    display: none;
}

/* Print stylesheet for the ROI Calculator showcase. The .roi-calculator-page
   wrapper now wraps the entire page (hero + main container + closing CTA),
   so all rules can scope to it. Inside the scope we override the MudBlazor
   palette CSS variables directly — that's the only reliable way to defeat
   the cosmic-theme dark colours that propagate via --mud-palette-* on every
   typography class.

   Goal: clean A4 sheet, black-on-white text + numbers, no charts, no
   interactive controls, no decorative paint, no marketing CTA. */
@media print {
    @page {
        size: A4;
        margin: 18mm 14mm;
    }

    /* Force the document and all chrome to plain white. */
    html, body {
        background: #ffffff !important;
        color: #000000 !important;
    }

    /* Hide global app chrome. */
    .mud-appbar,
    .mud-drawer,
    .site-footer,
    .article-toc-fab,
    .mud-scroll-to-top,
    body > .mud-popover-provider,
    body > .mud-snackbar-provider {
        display: none !important;
    }

    /* Inside the page scope: override the MudBlazor palette variables so
       every descendant that paints from --mud-palette-tertiary / primary /
       text-primary / background / surface inherits print-safe colours,
       not the cosmic-theme dark palette. This is the rule that fixes
       "Aqua-Pulse text on Cosmic-Black background" everywhere. */
    .roi-calculator-page,
    .roi-calculator-page * {
        --mud-palette-background: #ffffff !important;
        --mud-palette-surface: #ffffff !important;
        --mud-palette-text-primary: #000000 !important;
        --mud-palette-text-secondary: #333333 !important;
        --mud-palette-text-disabled: #777777 !important;
        --mud-palette-primary: #000000 !important;
        --mud-palette-secondary: #000000 !important;
        --mud-palette-tertiary: #000000 !important;
        --mud-palette-divider: #cccccc !important;
        --brand-cosmic-black: #ffffff !important;
        --brand-midnight-violet: #ffffff !important;
        --brand-deep-cosmos: #ffffff !important;
        --brand-night-violet: #ffffff !important;
        --brand-galaxy-purple: #ffffff !important;
        --brand-almost-white: #000000 !important;
        --brand-light-alloy: #333333 !important;
        background-color: transparent !important;
        background-image: none !important;
        color: #000000 !important;
        box-shadow: none !important;
        text-shadow: none !important;
    }

    /* Hero section is fully hidden on print — the print-header above carries
       the masthead (brand block + title + date), so the on-screen hero with
       its gradient backdrop and h3 title would be redundant. */
    .roi-calculator-page .hero-section {
        display: none !important;
    }

    /* Hide everything interactive or decorative. */
    .roi-calculator-page .roi-toolbar,
    .roi-calculator-page .mud-slider,
    .roi-calculator-page .roi-slider-row .mud-icon,
    .roi-calculator-page .mud-chart,
    .roi-calculator-page .mud-progress-linear,
    .roi-calculator-page .roi-actions,
    .roi-calculator-page .roi-back,
    .roi-calculator-page .roi-cta,
    .roi-calculator-page .mud-button,
    .roi-calculator-page .mud-icon-button,
    .roi-calculator-page .mud-fab,
    .roi-calculator-page .mud-expansion-panel-icon,
    .roi-calculator-page .mud-expand-panel-icon {
        display: none !important;
    }

    /* Print-only brand block at the top of the print header. The wordmark
       reads black on white because the print-scope palette override sets
       --brand-almost-white to #000, and "ai" reads in Aqua Pulse via the
       .brand-ai class which uses --brand-aqua-pulse (NOT remapped).
       Logo prints in its native colours: nebula violet on the left half
       reads on white paper; the white right half blends into the bg, so
       the masthead reads as "half-brain in nebula on white" — same intent
       as the on-screen treatment but without forcing the SVG to a solid
       silhouette. */
    .roi-calculator-page .roi-print-header .roi-hero-brand .brand-ai {
        color: var(--brand-aqua-pulse) !important;
    }

    /* Flatten the cosmic-card and MudPaper containers — no borders, no
       shadows, no full-bleed paint. Lets the layout collapse onto the
       white page background. */
    .roi-calculator-page .cosmic-card,
    .roi-calculator-page .mud-paper,
    .roi-calculator-page .mud-paper-square,
    .roi-calculator-page .mud-card,
    .roi-calculator-page .mud-expand-panel,
    .roi-calculator-page .mud-expand-panels {
        background: transparent !important;
        background-color: transparent !important;
        background-image: none !important;
        box-shadow: none !important;
        border: none !important;
        padding: 0 !important;
        margin: 0 0 0.75rem 0 !important;
    }

    /* Defensive expand-panel content rules. The methodology panel is opened
       programmatically before window.print() (PrintSummary in the razor
       sets _methodologyExpanded = true), but if the user expands it
       manually first we still need the content visible without MudBlazor's
       collapse animation interfering. */
    .roi-calculator-page .mud-expand-panel-text,
    .roi-calculator-page .mud-collapse-container,
    .roi-calculator-page .mud-collapse-wrapper,
    .roi-calculator-page .mud-collapse-wrapper-inner {
        max-height: none !important;
        height: auto !important;
        overflow: visible !important;
        visibility: visible !important;
        opacity: 1 !important;
        display: block !important;
        padding: 0 !important;
    }
    .roi-calculator-page .mud-expand-panel-header {
        padding: 0 !important;
        min-height: 0 !important;
        cursor: default !important;
    }

    /* Show the print-only self-identifying header. */
    .roi-calculator-page .roi-print-header {
        display: block !important;
        padding-bottom: 0.75rem;
        border-bottom: 1px solid #999 !important;
        margin-bottom: 1rem;
        font-size: 0.875rem;
    }

    /* Page-break management. Keep compact blocks intact across page breaks. */
    .roi-calculator-page .roi-slider-row,
    .roi-calculator-page .roi-formula-list li,
    .roi-calculator-page .roi-sensitivity-row,
    .roi-calculator-page .mud-grid > .mud-grid-item {
        page-break-inside: avoid;
        break-inside: avoid;
    }

    /* Section headings stick to their following content. */
    .roi-calculator-page .mud-typography-h2,
    .roi-calculator-page .mud-typography-h4,
    .roi-calculator-page .mud-typography-h5,
    .roi-calculator-page .mud-typography-h6,
    .roi-calculator-page .mud-typography-subtitle1,
    .roi-calculator-page .mud-typography-subtitle2 {
        page-break-after: avoid;
        break-after: avoid;
    }

    /* Orphan / widow control on long paragraphs. */
    .roi-calculator-page p,
    .roi-calculator-page .mud-typography {
        orphans: 3;
        widows: 3;
    }

    /* Plain text links — URLs are listed in the header anyway. */
    .roi-calculator-page .mud-link {
        color: inherit !important;
        text-decoration: none !important;
    }
}

/* Top-bar nav links rendered uppercase to match landing-page mockup.
   Targets MudButton-based nav in the appbar without editing markup. */
.mud-appbar .mud-button-text {
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 600;
}

/* Share buttons (LinkedIn / X / Copy link). Wraps cleanly on mobile,
   accent-coloured on hover for affordance. */
.share-bar {
    display: flex;
    gap: 4px;
    align-items: center;
    flex-wrap: wrap;
}
.share-bar--inline {
    margin: 0;
}
/* Reserved for a future sticky-sidebar caller (e.g. desktop side-rail on
   long-form articles). Not currently rendered by any page — every detail
   page uses the inline variant. Sticks below the global app-bar via the
   shared --site-sticky-top token in theme.css. */
.share-bar--floating {
    position: sticky;
    top: var(--site-sticky-top);
    flex-direction: column;
    align-self: flex-start;
}
.share-bar .mud-icon-button {
    color: var(--brand-aqua-pulse);
    transition: color 160ms ease, background 160ms ease;
}
.share-bar .mud-icon-button:hover {
    color: var(--brand-aqua-pulse);
    background: color-mix(in srgb, var(--brand-aqua-pulse) 12%, transparent);
}

/* ── Signage kiosk connection-status pip ──────────────────────────────────
   Driven entirely by ReconnectModal.razor.js (the SignalR circuit is down in
   the disconnected state, so no Blazor/scoped styling can be relied on here).
   Literal colours: this must render even if theme variables fail to load. */
#signage-conn-dot {
    position: absolute;      /* held inside the .signage container (position: relative), not the viewport */
    right: 14px;
    bottom: 14px;
    z-index: 60;             /* above dim overlay (50) + game takeover (51) so the health pip is always
                                visible; still below the reconnect <dialog> (browser top layer) */
    width: 11px;
    height: 11px;
    border-radius: 50%;
    pointer-events: none;
    background: #34D399;                 /* connected: calm green */
    box-shadow: 0 0 6px rgba(52, 211, 153, 0.55);
    opacity: 1;
    transition: background 200ms ease, box-shadow 200ms ease, opacity 200ms ease;
}
#signage-conn-dot[data-state="reconnecting"] {
    background: #FBBF24;                 /* amber */
    box-shadow: 0 0 8px rgba(251, 191, 36, 0.7);
    opacity: 1;
    animation: signage-conn-pulse 1s ease-in-out infinite;
}
#signage-conn-dot[data-state="disconnected"] {
    background: #EF4444;                 /* red */
    box-shadow: 0 0 9px rgba(239, 68, 68, 0.8);
    opacity: 1;
    animation: signage-conn-pulse 0.8s ease-in-out infinite;
}
@keyframes signage-conn-pulse {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.5); }
}
@media (prefers-reduced-motion: reduce) {
    #signage-conn-dot { animation: none !important; }
}

/* ── Signage kiosk portrait rotation ─────────────────────────────────────────
   Driven by js/signage-rotate.js, which sets data-signage-rotate on <html> ONLY on
   /signage?rotate=cw|ccw. The Samsung stretch panel hands the browser a LANDSCAPE
   viewport (≈1536×432) even when physically mounted portrait, and its hardware
   content-rotation does not affect the live web view — so we rotate the page ourselves.
   The .signage canvas is authored 540×1920 portrait; we rotate it 90° and scale
   (--rot-scale, computed by the JS from the actual viewport) to fill the landscape frame.
   Inert unless the attribute is present, so normal /signage and every other page are
   untouched. !important overrides Signage.razor.css's scoped position:relative. */
html[data-signage-rotate] { overflow: hidden; }
html[data-signage-rotate] body { overflow: hidden; }
html[data-signage-rotate] .signage {
    position: fixed !important;
    top: 50% !important;
    left: 50% !important;
    transform-origin: center center !important;
}
html[data-signage-rotate="cw"] .signage {
    transform: translate(-50%, -50%) rotate(90deg) scale(var(--rot-scale, 0.8)) !important;
}
html[data-signage-rotate="ccw"] .signage {
    transform: translate(-50%, -50%) rotate(-90deg) scale(var(--rot-scale, 0.8)) !important;
}
/* The reconnect modal is a body-level <dialog> (outside .signage), so the transform above never reaches
   it and it shows sideways on the rotated wall. It's small + centered, so a plain rotate matching the
   display direction keeps "Rejoining the server…" upright. */
/* The dialog's own [open] slide-up animation hard-sets `transform`, which overrides a plain rotate — so
   the modal stayed sideways. On the rotated display, drop that animation (keep it visible via opacity:1)
   so the rotation actually takes effect. */
html[data-signage-rotate] #components-reconnect-modal { animation: none !important; opacity: 1 !important; }
html[data-signage-rotate="cw"] #components-reconnect-modal { transform: rotate(90deg) !important; }
html[data-signage-rotate="ccw"] #components-reconnect-modal { transform: rotate(-90deg) !important; }
/* On the wall the modal was rendering see-through / unreadable. Whatever the cause (it should inherit the
   opaque violet box), force it explicitly on the display: solid box, light text, and a near-opaque dark
   backdrop so the bright signage content behind can never bleed through and wash out the message. */
html[data-signage-rotate] #components-reconnect-modal {
    background-color: var(--brand-midnight-violet, #11041F) !important;
    color: var(--brand-almost-white, #F7F7F7) !important;
}
html[data-signage-rotate] #components-reconnect-modal::backdrop {
    animation: none !important;
    opacity: 1 !important;
    background-color: rgba(11, 0, 24, 0.92) !important;
}
/* The splash is a body-level full-screen overlay; its starfield + gradient fill the screen fine in any
   orientation, but the centred logo/wordmark/tagline (.splash-content) show sideways. Rotate that content
   wrapper to match the display so the splash flash on reload is upright too. */
html[data-signage-rotate="cw"] #splash .splash-content { transform: rotate(90deg); }
html[data-signage-rotate="ccw"] #splash .splash-content { transform: rotate(-90deg); }
/* On the portrait wall the tagline renders too large once rotated; drop just the tagline on /signage and
   keep the logo + "Taight" wordmark. The marketing splash on normal pages keeps the full lockup. */
html[data-signage-rotate] #splash .splash-tagline { display: none !important; }
