{{-- REP-P1-2: shared-report URLs are public-but-private — anyone with the token can read the report, but they must NOT be indexed. Defense-in- depth alongside the `X-Robots-Tag` HTTP header set in SharedReportLinkController. Tokens that leak to public channels (Slack, Twitter, GitHub README link previewers) would otherwise become discoverable via `site:` queries. --}} @if(request()->is('shared-reports/*')) @endif {{-- Canonical + hreflang: public/marketing routes only. App-internal routes (dashboard, settings, billing, admin, site-scoped pages) intentionally omitted — authenticated pages are not indexable and generic canonicals would harm SEO for shared public URLs. --}} @unless(request()->is( 'dashboard*', 'profile*', 'settings*', 'billing*', 'admin*', 'sites/*', 'portfolio*', 'export/*', 'notifications*', 'api/*', 'oauth/*', 'wp/*', 'shared-reports/*' )) {{-- SEO-003: Strip query params from hreflang so /pricing?billing=annual doesn't generate a duplicate hreflang signal for Google. R3SEO-006: root path "/" must include trailing slash in hreflang to match the homepage canonical (${appUrl} without trailing slash is normalised by WelcomeHead; hreflang now always uses url() with no-trailing-slash policy so both resolve identically). --}} @php $hreflangHref = request()->is('/') ? url('/') : url(request()->path()); @endphp {{-- D10-A-003: bare "en" covers English-language users regardless of region (en-GB, en-AU, etc.). --}} @endunless {{-- SVG favicon (highest priority for modern browsers — vector, scales perfectly). Inlined as a data URI to avoid an extra request and survive aggressive CDN/cache rules. Renders the simplified mark: full-bleed brand-purple rounded square + white crown + amber sparkle. Source of truth: public/branding/masters/icon-simplified.svg. --}} {{-- Theme FOUC guard: apply the persisted theme BEFORE any Vite script loads, so a dark-mode user never sees a white flash → dark repaint on cold load. ThemeProvider.tsx applies the theme only post-hydration; this tiny blocking script runs first and sets the .dark class synchronously. It MUST mirror ThemeProvider's storage scheme exactly: localStorage key `theme`, values `light|dark|system`, and `system` resolved against `prefers-color-scheme`. Carries the CSP nonce like the JSON-LD/GA scripts. Keep minimal + synchronous (no external deps). --}} {{-- Theme color: initial value matches light-mode brand purple. ThemeProvider.tsx updates this single tag dynamically based on resolved theme (light → #7C3AED / dark → #5B21B6), so media-attribute variants are not needed. --}} {{-- Open Graph defaults. Per-page Inertia overrides these. --}} {{-- D10-C-007: global twitter:card default — per-page Head overrides take precedence. Ensures all pages get summary_large_image even without an explicit per-page card tag. --}} {{-- Schema.org Organization — only on public pages so authenticated routes don't get indexed. --}} @unless(request()->is( 'dashboard*', 'profile*', 'settings*', 'billing*', 'admin*', 'sites/*', 'portfolio*', 'export/*', 'notifications*', 'api/*', 'oauth/*', 'wp/*', 'shared-reports/*' )) {{-- R3SEO-007: Single authoritative Organization node — @id, logo, sameAs. WelcomeHead.tsx must NOT emit a second Organization node. This is the canonical entity that all other pages reference via publisher/@id = "{{url('/')}}/#organization". --}} @endunless {{-- Prefetch high-traffic marketing pages — only for guests. Logged-in users on /dashboard would otherwise prefetch /features + /pricing on every page load (~30-60 kB unused bandwidth on mobile). The marketing surface is also where these prefetches actually help — a guest visitor hopping from the homepage to /features benefits; an authenticated user almost never does. (F-PERF-09) --}} @guest @endguest {{-- SEO-002: Font loading strategy. Inter (primary UI font) and JetBrains Mono (`.font-data`) load on every page because both are used across dashboard, auth, sites, and marketing — `font-data` shows up on Roi/Dashboard, ContentEditor, Auth/TwoFactorChallenge, Sites/*, OpportunityMap, plus all marketing surfaces. Caveat (`.annotation` cursive in `AnnotatedScreenshot`) is loaded ONLY on Welcome — the single page that consumes it — and with `display=optional` so the cursive face either appears immediately or is skipped entirely (no fallback→Caveat swap, no CLS). The previous `display=swap` produced a measurable layout shift on rotated, absolutely-positioned annotations when the cursive face arrived. (F-PERF-02, F-PERF-03) Explicit woff2 preloads on Inter 400/600 give the LCP-critical weights priority over Mono's font requests; without preload, all ~9 woff2 files raced for HTTP/2 priority. (F-PERF-01) --}} {{-- D8-C-004: Inter 500 preload — used in button labels and nav links; previously raced with 600+ --}} {{-- D8-C-007: JetBrains Mono 400 preload — .font-data tables; appears on Dashboard + ROI pages --}} @if(request()->is('/')) {{-- Caveat is only used by AnnotatedScreenshot annotations on Welcome. display=optional avoids the swap-induced layout shift. --}} @endif @unless(request()->is( 'dashboard*', 'profile*', 'settings*', 'billing*', 'admin*', 'sites/*', 'portfolio*', 'export/*', 'notifications*', 'api/*', 'oauth/*', 'wp/*', 'shared-reports/*' )) {{-- Bricolage Grotesque: display/heading font for marketing pages only. Provides typographic contrast layer vs. body Inter (gauntlet H-03). --}} {{-- D8-C-008: preload Bricolage 700 — the LCP heading weight on all marketing pages --}} @endunless {{-- Google Analytics 4 - Production Only (with Consent Mode v2) --}} @production @if(config('services.google.analytics_id')) @endif @endproduction @routes(null, Illuminate\Support\Facades\Vite::cspNonce()) @viteReactRefresh @vite(['resources/js/app.tsx', "resources/js/Pages/{$page['component']}.tsx"]) @inertiaHead @inertia