/*
 * CLAUDE-CA1D-PUBLIC-LANDING-01: public front door (archiosk.com/,
 * /explore, /start-trial). Deliberately its OWN, self-contained stylesheet
 * -- NOT main.css's shared token system. The authenticated app's design
 * grammar is tonal/restrained-by-design (main.css's own header: color
 * used only for real semantic meaning); this surface is a different
 * thing entirely -- an atmospheric public front door descended from the
 * Archiosk Holodeck lineage (C:\Archiosk\holodeck\archive\
 * archiosk_holodeck_v_3.html), never the authenticated product itself.
 * Carried forward from that artifact: the dark aqueous gradient field,
 * a canvas particle layer that responds to the cursor, a ghost-intro
 * title reveal, and a glow/hover-brightens-on-focus interaction language.
 * Deliberately NOT carried forward: the swimming "fish" navigation
 * words, the PDB/CM/DB environment rooms and their relationship
 * diagrams/side-lists, and the contact-bubble/mailto form -- those
 * belonged to the deeper educational Holodeck environment, not a
 * commercial front door (see the Product Owner's own "do not carry
 * forward" list).
 *
 * CLAUDE-CA1D-PUBLIC-LANDING-01 (background adjustment): base gradient
 * stops and radial-accent opacity retuned against a second reference --
 * C:\Archiosk\holodeck\archive\archiosk-holodeck.before-
 * RESTORE_BASELINE_V3_ATOMIC_HOME_WORDPRESS_BLOCK_ONLY...html, whose own
 * root background (rgb 2/8/18, rgb 3/23/37, rgb 1/5/10) and later
 * "arch-navy" constant (rgb 0/8/20) are both much closer to true
 * navy-black than this file's original, brighter teal-leaning base.
 * That reference's own radial accents are more saturated in hue but run
 * at LOW opacity (0.10-0.12) against that near-black base -- restraint
 * comes from opacity against darkness, not from duller hues. Retuned to
 * match that principle: darker base stops, radial-accent opacity
 * roughly halved, hues left as this file's own (more muted than the
 * reference's) to avoid the bright-cyan-wash/neon look explicitly
 * ruled out.
 */

/* CLAUDE-LANDING-CENTERING-01. Reported from a phone: "the landing page on
   my phone is not centered in portrait position but it is ok in landscape."

   The arithmetic, not a guess. .landing-content below asks for a min-height
   of 100dvh AND 8vh/10vh of vertical padding. Under the CSS default of
   content-box, padding is added OUTSIDE that height - so the flex container
   that is meant to fill the screen is 118dvh tall, and `justify-content:
   center` faithfully centres its content inside a box 18% taller than the
   viewport. The content sits low and the page scrolls.

   Landscape hid it: 18% of a short viewport is ~90px rather than ~150px, and
   the hero is short enough there that the overflow stayed under the fold.
   Same defect, quieter symptom - which is why it read as a portrait-only bug.

   Scoped to this page's own subtree rather than declared globally, because
   landing.css is loaded by the public shell alone and a bare `*` rule here
   would still be a wider claim than the fix needs. */
.landing-page,
.landing-page *,
.landing-page *::before,
.landing-page *::after { box-sizing: border-box; }

.landing-page {
    position: relative;
    /* CLAUDE-MOBILE-ICON-01 correction: 100dvh, not 100vh. On iOS Safari
       100vh is the height the viewport WOULD have with the browser chrome
       hidden, so a 100vh block is taller than what the reviewer can actually
       see and its lower content sits below the frame. main.css already made
       this correction for the authenticated shell
       (CLAUDE-MOBILE-SHELL-STABILITY-01); the landing page never got it, and
       adding the brand icon above the wordmark is what finally made the
       overflow visible. The plain 100vh stays first as the fallback for
       browsers without dvh. */
    min-height: 100vh;
    min-height: 100dvh;
    width: 100%;
    overflow-x: hidden;
    background:
        radial-gradient(circle at 50% 10%, rgba(33, 112, 132, .14), transparent 30%),
        radial-gradient(circle at 50% 45%, rgba(8, 55, 68, .12), transparent 42%),
        linear-gradient(180deg, rgb(2, 8, 18) 0%, rgb(3, 23, 37) 46%, rgb(1, 5, 10) 100%);
    color: rgb(234, 252, 255);
    font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    isolation: isolate;
}

.landing-field-canvas {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 0;
    display: block;
}
/* Static-image fallback shown instead of the canvas when JS never runs
   (disabled/blocked) or prefers-reduced-motion is set -- never a blank
   background either way. */
.landing-field-canvas.is-static { display: none; }
.landing-page.no-motion .landing-field-canvas { display: none; }

/* CLAUDE-CA1D-PUBLIC-LANDING-01 consolidated addendum, Sections B3/C1-C3:
   the ambient knowledge field -- sparse rising bubbles, small drifting
   knowledge-particle glyphs, real (never invented) writing-system
   fragments, and occasional larger GO domain-signal words. All are
   plain generated <span>/<div> elements (landing.js), never canvas text
   -- lets the browser's own font stack handle real Unicode scripts
   correctly rather than this code trying to render/shape them itself.
   Sits behind the hero content (z-index 1, between the canvas at 0 and
   .landing-content at 2) and is entirely inert (pointer-events: none) --
   decorative atmosphere only, never intercepts a click meant for a real
   control. Skipped entirely under prefers-reduced-motion, same as the
   canvas particle field above.

   CLAUDE-CA1D-PUBLIC-LANDING-04: depth/parallax + upward-convection
   rework -- same DOM node count and same four content tiers as before
   (no new particle budget, Section 10's own "prefer a small number of
   well-behaved objects"), but each item now also carries a depth tier
   (near/mid/far -- static/js/landing.js's DEPTH_CONFIG) expressed
   entirely through CSS custom properties (--kf-scale/--kf-peak-opacity)
   consumed by the ONE shared kfRise keyframe below, and an optional
   "in a current" membership that tightens its horizontal spawn point
   toward one of two named VENTS and shortens its rise duration --
   never a literal vent graphic, only motion (Section 2's own "presence
   should be inferred mainly from motion"). The three intermediate
   translateX stops (35%/65%/100%, each independently randomized per
   item -- --kf-drift-1/-2/-3) replace the old single linear 0%->100%
   drift, giving a gentle non-monotonic meander instead of a straight
   diagonal line, with the largest wander reserved for the final stage
   ("drift sideways or spiral slightly as they leave the strongest part
   of the current", Section 2). Still pure CSS transform/opacity
   animation -- no rAF loop, no added DOM nodes, no per-frame JS. */
.landing-knowledge-field {
    position: fixed;
    inset: 0;
    z-index: 1;
    overflow: hidden;
    pointer-events: none;
}
.kf-item {
    position: absolute;
    top: 100%;
    left: 0;
    color: rgba(198, 255, 244, .5);
    font-family: Inter, ui-sans-serif, system-ui, sans-serif;
    white-space: nowrap;
    will-change: transform, opacity;
    animation-name: kfRise;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
    --kf-scale: 1;
    --kf-peak-opacity: 1;
    --kf-drift-1: 0px;
    --kf-drift-2: 0px;
    --kf-drift-3: 0px;
}
/* Background layer (Section 3): smaller, dimmer, softer, almost
   atmospheric -- a small blur is the one property that can't be
   expressed as a --kf-* custom property feeding the shared keyframe,
   so it stays a real class instead. */
.kf-depth-far { filter: blur(.5px); }
/* Tier: sparse rising bubbles (B3) -- plain translucent circles, not
   canvas/emoji "cartoon" bubbles. */
.kf-bubble {
    border-radius: 50%;
    background: radial-gradient(circle at 35% 30%, rgba(210, 255, 248, .22), rgba(140, 220, 235, .05) 70%);
    border: 1px solid rgba(190, 255, 244, .10);
}
/* Tier: small knowledge particles (C1) -- numbers/math/musical notation/
   plain letters. */
.kf-particle { font-size: 1rem; opacity: .16; color: rgba(190, 255, 244, .6); }
/* Tier: real writing-system fragments (C2) -- see landing.js for the
   actual character set and its own sourcing note. Slightly larger/more
   legible than tier 1 particles (still low-opacity, still subordinate),
   since an unrecognizable single glyph is more legible at this size. */
.kf-script { font-size: 1.3rem; opacity: .14; color: rgba(205, 255, 246, .62); }
/* Tier: occasional GO domain-signal words (C3) -- larger, letter-spaced
   like a signal/label, but NOT a nav menu (no pointer-events, no href,
   nothing clickable) and still low-opacity/slow -- a recognizable
   fragment moving through the field, not a button. */
.kf-term {
    font-size: .82rem;
    font-weight: 700;
    letter-spacing: .16em;
    text-transform: uppercase;
    opacity: .12;
    color: rgba(150, 235, 255, .7);
}
@keyframes kfRise {
    0%   { transform: translateY(0) translateX(0) scale(var(--kf-scale)); opacity: 0; }
    8%   { opacity: var(--kf-peak-opacity); }
    35%  { transform: translateY(-39vh) translateX(var(--kf-drift-1)) scale(var(--kf-scale)); }
    65%  { transform: translateY(-73vh) translateX(var(--kf-drift-2)) scale(var(--kf-scale)); }
    88%  { opacity: var(--kf-peak-opacity); }
    100% { transform: translateY(-112vh) translateX(var(--kf-drift-3)) scale(var(--kf-scale)); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
    .landing-knowledge-field { display: none; }
}

/* CLAUDE-CA1D-PUBLIC-LANDING-03, Section 1: the opening signal-streak
   prelude -- one or two brief, fast luminous traversals that read as
   "the environment awakens" BEFORE ARCHIOSK's own slower arrival below.
   Deliberately NOT part of the infinite .kf-item loop above: this is a
   one-shot event, plain server-rendered markup with a single forwards-
   filled keyframe (ends at opacity 0 and simply stays there -- no JS
   timer needed to clean it up, no repeat). A thin gradient line with a
   soft glow, never a literal object/asset -- Archiosk's own visual
   language (the same aqueous teal/cyan already used throughout this
   file), not a franchise reference. Sits above the knowledge field
   (z-index 1) so it reads clearly against the deep background during
   the otherwise-quiet opening beat, entirely inert (pointer-events:
   none). Hidden outright under prefers-reduced-motion, same as every
   other motion layer on this page. */
.landing-signal-streak {
    position: fixed;
    top: 50%;
    left: 50%;
    width: 15vw;
    height: 2px;
    background: linear-gradient(90deg, transparent, rgba(150, 255, 238, 0) 0%, rgba(190, 255, 244, .9) 55%, rgba(220, 255, 250, 1) 78%, transparent 100%);
    border-radius: 2px;
    box-shadow: 0 0 12px rgba(150, 255, 238, .8), 0 0 28px rgba(80, 230, 255, .4);
    z-index: 1;
    pointer-events: none;
    opacity: 0;
    will-change: transform, opacity;
}
/* CLAUDE-CA1D-PUBLIC-LANDING-05, Section 6: ONE object only (was two,
   landing-signal-streak-2 removed outright -- "no multiple shooting
   lights").

   CLAUDE-CA1D-PUBLIC-LANDING-ANIMATION-CORRECTION-02: a real Product
   Owner correction -- the previous path (a long diagonal translate3d
   sweep at a near-constant size) read as "a glowing stick/plank sliding
   sideways," not a forward launch. Redesigned as a converging path
   toward the exact vanishing point instead of a lateral crossing: the
   destination is (0, 0) -- screen center, precisely where ARCHIOSK is
   about to materialize, i.e. the "horizon" this element is meant to
   fly INTO. `rotate(-30deg)` is a fixed alignment angle (never
   animated) matching the start->center vector, so the bar visually
   points along its own direction of travel throughout, like a thrown
   spear rather than a plank drifting past. `scaleX` does the
   "perspective scaling/tapering" the Product Owner asked for in place
   of a literal 3D camera: it grows through the fast-motion middle
   stretch (a motion-blur-like elongation aligned with the travel
   vector, per Section "subtle motion blur aligned with the direction
   of travel") then tapers sharply to near-nothing exactly as it
   reaches center and fades -- "diminish/disappear into the field," not
   a pass-through past the far edge.

   CLAUDE-CA1D-PUBLIC-LANDING-ANIMATION-CORRECTION-01: fully invisible
   again (150ms delay + .95s duration = done by ~1.1s) BEFORE the
   wordmark's own materialization begins at 1.3s -- "light arrives,
   light disappears, THEN Archiosk manifests," a real sequence rather
   than the two effects overlapping. */
.landing-signal-streak-1 {
    animation: landingSignalStreak1 .95s cubic-bezier(0.22, 0.61, 0.36, 1) 150ms forwards;
}
@keyframes landingSignalStreak1 {
    0%   { transform: translate3d(-32vw, 18vh, 0) rotate(-30deg) scaleX(.5); opacity: 0; }
    12%  { opacity: 1; }
    50%  { transform: translate3d(-14vw, 7vh, 0) rotate(-30deg) scaleX(1.7); opacity: 1; }
    82%  { opacity: .85; }
    100% { transform: translate3d(0, 0, 0) rotate(-30deg) scaleX(.08); opacity: 0; }
}

.landing-content {
    position: relative;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    min-height: 100dvh; /* see .landing-page above */
    padding: 8vh 24px 10vh;
    text-align: center;
}

.landing-wordmark {
    /* CLAUDE-LANDING-SIMPLIFY-01: was Georgia serif, which made the wordmark
       the one serif object on an otherwise entirely sans-serif surface -- and
       inconsistent with the authenticated shell, whose own wordmark
       (main.css) has always been sans. This is the SAME stack .landing-page
       itself uses, so the page now speaks one typographic language and
       ARCHIOSK is simply its strongest expression: distinction comes from
       scale, weight and tracking rather than from a second typeface.
       Deliberately not "Space Grotesk" -- no font file is shipped for it, so
       it renders only where a machine happens to have it, and main.css's own
       test asserts that name appears exactly once in this codebase. */
    font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    font-weight: 600;
    font-size: clamp(2.8rem, 8.4vw, 6rem);
    letter-spacing: .18em;
    text-transform: uppercase;
    color: rgba(230, 244, 255, .92);
    text-shadow: 0 0 22px rgba(165, 255, 244, .22), 0 0 54px rgba(79, 255, 231, .10);
    margin: 0;
    opacity: 0;
    /* CLAUDE-CA1D-PUBLIC-LANDING-01 consolidated addendum, Section B2:
       a real arrival, not a fade-up -- adapted from archiosk_holodeck_v_3
       .html's own ah-intro-title (scale(4.4) settling to scale(1) over
       ~5s, cubic-bezier(0.18, 0.84, 0.22, 1)) and the second reference's
       ahV3ArchioskArrival. Unlike that source's own intro (which fully
       fades OUT afterward, making room for a separate scene), ARCHIOSK
       is this page's permanent identity, so it settles and STAYS
       visible -- never returns to opacity 0.
       CLAUDE-CA1D-PUBLIC-LANDING-ANIMATION-CORRECTION-01: start delayed
       1.3s (was 500ms) -- a real Product Owner correction found the
       previous timing had the wordmark already emerging WHILE the
       signal streak was still traversing the field (streak fades out
       ~1.1s; wordmark used to start at 0.5s), reading as two overlapping
       effects rather than "light arrives -> light disappears -> Archiosk
       manifests." 1.3s leaves a deliberate ~200ms quiet beat after the
       streak is fully gone before the whole text family begins to
       materialize -- every downstream reveal below (tagline/actions/
       voice) re-anchored off this same 1.3s start, each still following
       the streak's own disappearance, never overlapping it. */
    animation: landingWordmarkArrival 1.9s cubic-bezier(0.18, 0.84, 0.22, 1) 1.3s forwards;
}
.landing-tagline {
    margin: 14px 0 0;
    color: transparent;
    background: linear-gradient(90deg, rgba(60, 255, 218, 1), rgba(210, 255, 236, .96), rgba(56, 218, 255, 1));
    -webkit-background-clip: text;
    background-clip: text;
    font-size: clamp(.85rem, 1.6vw, 1.05rem);
    font-weight: 600;
    letter-spacing: .26em;
    text-transform: uppercase;
    opacity: 0;
    animation: landingTextMaterialize 1.3s ease forwards 1.75s;
}
/* CLAUDE-CA1D-PUBLIC-LANDING-ANIMATION-CORRECTION-01: "start at
   opacity: 0, with a soft blur/haze, slightly scaled/diffused, then
   transition into fully sharp, crisp, readable text... like an
   apparition emerging from ether" -- shared by every remaining "text
   family" member below the wordmark itself (tagline/actions/voice; the
   wordmark keeps its own more pronounced landingWordmarkArrival, below,
   since it settles from a much larger scale). Replaces this file's
   previous, simpler fade-and-slide-up reveal treatment (opacity+
   translateY only, no blur-driven "diffuse" quality) -- deliberately
   drops the vertical slide entirely; a pure blur+scale+opacity resolve
   reads as materializing in place rather than sliding into position,
   closer to the requested "apparition" quality than a conventional
   fade-up. */
@keyframes landingTextMaterialize {
    from { opacity: 0; transform: scale(1.12); filter: blur(9px); }
    to   { opacity: 1; transform: scale(1); filter: blur(0); }
}
@keyframes landingWordmarkArrival {
    0%   { opacity: 0; transform: translateY(0) scale(3.2); filter: blur(16px); }
    30%  { opacity: 1; filter: blur(3px); }
    62%  { opacity: 1; transform: scale(1.07); filter: blur(0); }
    100% { opacity: 1; transform: scale(1); filter: blur(0); }
}

/* CLAUDE-CA1D-PUBLIC-LANDING-05, Sections 1/2: the static explanatory
   sentence (.landing-value-prop) and the visible rotating philosophical
   line (.landing-rotator/.landing-rotator-line) that used to live here
   are both removed outright -- "do not replace them with another
   visual text carousel." Their meaning now lives in the spoken welcome
   greeting (static/js/landing.js's setUpSpokenWelcome) and in
   /explore's own fuller explanation. Removing them also directly
   satisfies Section 7's "comfortable viewport clearance" requirement --
   .landing-actions now follows the tagline much more closely, so the
   settled hero reads as a compact, uncluttered center rather than a
   tall stack competing for vertical space. */
.landing-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    justify-content: center;
    margin-top: 48px;
    opacity: 0;
    animation: landingTextMaterialize 1.3s ease forwards 2.05s;
}
.landing-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 14px 30px;
    border-radius: 999px;
    font-family: inherit;
    font-size: .92rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-decoration: none;
    transition: transform 220ms ease, filter 220ms ease, box-shadow 220ms ease;
}
.landing-action-primary {
    color: rgb(4, 20, 26);
    background: linear-gradient(120deg, rgba(60, 255, 218, .96), rgba(105, 224, 255, .92));
    box-shadow: 0 0 24px rgba(79, 255, 231, .22);
}
.landing-action-secondary {
    color: rgba(232, 255, 251, .92);
    background: rgba(20, 60, 70, .38);
    border: 1px solid rgba(176, 219, 255, .28);
}
.landing-action:hover, .landing-action:focus-visible {
    transform: translateY(-2px);
    filter: brightness(1.08);
    box-shadow: 0 0 34px rgba(100, 255, 236, .28);
}
.landing-action:focus-visible {
    outline: 2px solid rgba(200, 230, 255, .8);
    outline-offset: 3px;
}

/* CLAUDE-CA1D-PUBLIC-LANDING-03, Section 3/7 (icon-only per LANDING-05,
   Section 8): "Speak to Archiosk" -- an additional entry path alongside
   Explore/Request Trial Access/Sign In, never a replacement for them
   (Section 9) -- deliberately quieter than .landing-action (no gradient
   fill, no glow-on-idle) so the commercial CTA row above stays visually
   primary (Section 7's own hierarchy). Reuses the exact same JS
   mechanism and consent language as the authenticated composer's own
   mic button (CLAUDE-POSTCAMEL-VOICE1-PRE, static/js/case_workspace.js)
   -- same hidden-until-feature-detected default, same push-to-talk
   model, same voice-input-listening state class name (kept identical
   rather than inventing a parallel one, even though this file never
   loads main.css). LANDING-05, Section 8: compact circular icon button
   -- no visible "Speak to Archiosk" text (the aria-label/title in
   landing.html carry the same meaning for assistive tech and
   mouse-hover alike); a real <button>, so keyboard focus/activation
   need no extra wiring here. */
.landing-voice {
    margin-top: 28px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    opacity: 0;
    animation: landingTextMaterialize 1.3s ease forwards 2.25s;
}
.landing-voice-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border-radius: 50%;
    font-size: 1.05rem;
    color: rgba(210, 255, 248, .75);
    background: transparent;
    border: 1px solid rgba(176, 219, 255, .22);
    cursor: pointer;
    transition: border-color 220ms ease, color 220ms ease, box-shadow 220ms ease;
}
.landing-voice-button:hover, .landing-voice-button:focus-visible {
    color: rgba(230, 244, 255, .95);
    border-color: rgba(176, 219, 255, .5);
}
.landing-voice-button:focus-visible {
    outline: 2px solid rgba(200, 230, 255, .8);
    outline-offset: 3px;
}
/* Section 7: "restrained aperture pulse... quiet change in microphone
   state" -- a slow, gentle ring pulse, never a large blob or an
   equalizer. The ONLY visual state change while listening, matching
   the authenticated composer's own "no separate recording timer/
   waveform UI" minimalism. */
.landing-voice-button.voice-input-listening {
    color: rgba(230, 244, 255, .98);
    border-color: rgba(150, 255, 238, .8);
    box-shadow: 0 0 0 0 rgba(150, 255, 238, .5);
    animation: landingVoicePulse 1.8s ease-in-out infinite;
}
@keyframes landingVoicePulse {
    0%   { box-shadow: 0 0 0 0 rgba(150, 255, 238, .45); }
    70%  { box-shadow: 0 0 0 10px rgba(150, 255, 238, 0); }
    100% { box-shadow: 0 0 0 0 rgba(150, 255, 238, 0); }
}
.landing-voice-status {
    font-size: .74rem;
    color: rgba(190, 235, 230, .58);
    min-height: 1em;
}
.landing-voice-status[data-state="error"] { color: rgba(255, 200, 170, .8); }
.landing-voice-result {
    margin-top: 4px;
    max-width: 480px;
    padding: 14px 18px;
    border-radius: 12px;
    background: rgba(20, 60, 70, .28);
    border: 1px solid rgba(176, 219, 255, .18);
    color: rgba(228, 243, 255, .82);
    font-size: .88rem;
    line-height: 1.55;
}
.landing-voice-result a {
    color: rgba(150, 255, 238, .95);
    font-weight: 700;
}
/* Was an inline .style.margin write from landing.js. It moved here with the
   voice convergence: the response paragraph's spacing is a property of the
   card, and the card is described in one place. */
.landing-voice-answer { margin: 0 0 10px; }
.landing-voice-transcript {
    display: block;
    margin-bottom: 6px;
    color: rgba(190, 235, 230, .62);
    font-size: .78rem;
    font-style: italic;
}

.landing-footer {
    position: relative;
    z-index: 2;
    text-align: center;
    padding: 0 24px 32px;
    color: rgba(180, 230, 226, .42);
    font-size: .72rem;
    letter-spacing: .08em;
}
.landing-footer a { color: rgba(200, 230, 255, .62); }

/* Explore / Start Trial pages: same field/atmosphere, a plainer
   document-like content column instead of the centered hero. */
.landing-doc {
    position: relative;
    z-index: 2;
    max-width: 720px;
    margin: 0 auto;
    padding: 10vh 24px 10vh;
}
.landing-doc-back {
    display: inline-block;
    margin-bottom: 40px;
    color: rgba(200, 230, 255, .7);
    font-size: .82rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    text-decoration: none;
}
.landing-doc-back:hover, .landing-doc-back:focus-visible { color: rgba(230, 244, 255, .95); }
.landing-doc h1 {
    font-family: Georgia, "Times New Roman", serif;
    font-weight: 400;
    font-size: clamp(2rem, 5vw, 3rem);
    letter-spacing: .04em;
    color: rgba(230, 244, 255, .94);
    margin: 0 0 6px;
}
.landing-doc-kicker {
    display: block;
    margin-bottom: 14px;
    color: rgba(120, 255, 225, .8);
    font-size: .74rem;
    font-weight: 800;
    letter-spacing: .24em;
    text-transform: uppercase;
}
.landing-doc-section {
    margin-top: 32px;
}
.landing-doc-section h2 {
    font-size: .82rem;
    font-weight: 800;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: rgba(185, 255, 245, .68);
    margin: 0 0 10px;
}
.landing-doc-section p, .landing-doc-section li {
    color: rgba(224, 255, 250, .78);
    font-size: 1rem;
    line-height: 1.68;
}
.landing-doc-section ul { margin: 0; padding-left: 1.2em; }
.landing-doc-section li { margin-bottom: 8px; }
.landing-doc-actions {
    margin-top: 48px;
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
}

/* CLAUDE-CA1D-TRIAL-ACCESS-HOTFIX-01: the Request Trial Access form --
   same restrained dark/teal language as the rest of this file, high
   enough contrast on the input text itself (near-white) that the
   deep-ocean background never competes with actually typing into the
   field. */
.landing-request-form {
    /* CLAUDE-REQUEST-ACCESS-PRUNE-01: centred as a column now that the page
       is a heading and a form and nothing else. The 480px measure is
       unchanged - it is a comfortable line length for the labels - but with
       the explanatory paragraph and the footer buttons removed, a left-hung
       column left the form stranded against one edge of an otherwise empty
       page. `margin-inline: auto` centres the column itself; the fields
       inside stay left-aligned, because a centred LABEL over a full-width
       input has no common edge to read down. */
    margin-top: 32px;
    margin-inline: auto;
    display: flex;
    flex-direction: column;
    gap: 18px;
    max-width: 480px;
    width: 100%;
}
/* The one action on the page. Centred under the fields rather than hung on
   the left edge, and sized to its own text instead of stretching the width
   of the form - a full-bleed button reads as a banner, not a control. */
.landing-request-form .landing-action-primary {
    align-self: center;
    margin-top: 6px;
    min-width: 200px;
    text-align: center;
}
.landing-form-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    font-size: .85rem;
    color: rgba(200, 230, 255, .72);
}
.landing-form-field input,
.landing-form-field textarea {
    font-family: inherit;
    font-size: .95rem;
    color: rgba(234, 255, 251, .95);
    background: rgba(10, 35, 42, .55);
    border: 1px solid rgba(176, 219, 255, .28);
    border-radius: 6px;
    padding: 10px 12px;
    resize: vertical;
}
.landing-form-field input:focus-visible,
.landing-form-field textarea:focus-visible {
    outline: 2px solid rgba(200, 230, 255, .8);
    outline-offset: 1px;
    border-color: rgba(176, 219, 255, .6);
}
.landing-form-error {
    margin: 0;
    padding: 10px 14px;
    border-radius: 6px;
    background: rgba(120, 40, 30, .28);
    border: 1px solid rgba(255, 150, 120, .4);
    color: rgba(255, 210, 195, .92);
    font-size: .88rem;
}

@media (max-width: 640px) {
    .landing-actions { flex-direction: column; width: 100%; max-width: 320px; }
    .landing-action { width: 100%; }
}

/* Product Owner's own explicit requirement: respect
   prefers-reduced-motion -- every animation/transition above disabled
   outright, not merely shortened, and the canvas particle field is
   skipped entirely (landing.js checks the same media query before ever
   starting its render loop). */
@media (prefers-reduced-motion: reduce) {
    .landing-wordmark, .landing-tagline, .landing-actions, .landing-voice {
        animation: none !important;
        opacity: 1 !important;
        transform: none !important;
        filter: none !important;
    }
    .landing-action { transition: none; }
    /* CLAUDE-CA1D-PUBLIC-LANDING-03, Section 1: the one-shot prelude
       never even flashes under reduced motion -- display:none, not
       merely animation:none, since the un-animated base state is
       opacity:0 anyway (nothing would be visible either way, but this
       makes the intent explicit and matches .landing-knowledge-field's
       own treatment above). */
    .landing-signal-streak { display: none; }
    /* Section 7: the listening-state pulse is a genuine animation, not
       a one-off reveal -- disabled outright; .landing-voice-button
       still shows its plain border-color state change on click, which
       needs no motion at all. */
    .landing-voice-button.voice-input-listening { animation: none; }
}

/* ============================================================
   CLAUDE-MOBILE-ICON-01 / CLAUDE-MOBILE-PWA-01
   ============================================================ */

/* The landing brand: icon above wordmark, read as one composition.
   Sized modestly on purpose — this is the entrance, and the entry actions
   below matter more than the badge above them. "Avoid pushing the primary
   entry action too far down on mobile" is a sizing instruction as much as a
   layout one. EXPERIMENTAL until Product Owner visual acceptance. */
.landing-brand {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.7rem;
}
.landing-app-icon {
    /* CLAUDE-MOBILE-ICON-01 correction, Product Owner: "make the landing page
       icon tighter as they go beyond the screen frame."

       Sized against the WORDMARK rather than in fixed pixels, so the two
       always scale together and the composition can never grow past what the
       wordmark itself already fits into: the wordmark is
       clamp(2.8rem, 8.4vw, 6rem), and the icon is deliberately a little under
       its cap height. A fixed px icon beside a fluid wordmark is what let the
       pair get taller than the frame on a small phone in the first place. */
    width: clamp(38px, 7vw, 64px);
    height: clamp(38px, 7vw, 64px);
    border-radius: clamp(9px, 1.7vw, 15px);
    display: block;
    flex-shrink: 0;
}
@media (max-width: 640px) {
    /* Tighter still on a phone: the icon is a badge above the name, not a
       second headline, and the entry actions matter more than either. */
    .landing-app-icon {
        width: 44px;
        height: 44px;
        border-radius: 10px;
    }
    .landing-brand { gap: 0.35rem; }
}

/* The update notice, duplicated from main.css ON PURPOSE. landing_shell.html
   loads this file alone - no tokens.css, no main.css - so the notice would be
   unstyled on the one page an installed app cold-launches into. Literal colours
   rather than var() for the same reason: there are no tokens here. */
.update-notice {
    position: fixed;
    left: max(0.6rem, env(safe-area-inset-left));
    right: max(0.6rem, env(safe-area-inset-right));
    bottom: calc(env(safe-area-inset-bottom) + 0.6rem);
    z-index: 60;
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.6rem 0.75rem;
    border: 1px solid rgba(176, 219, 255, .28);
    border-radius: 8px;
    background: rgba(9, 34, 43, .96);
    box-shadow: 0 6px 20px rgba(0, 0, 0, .35);
    font-size: .82rem;
    color: rgba(232, 255, 251, .92);
}
.update-notice-text { flex: 1 1 auto; min-width: 0; }
.update-notice-action {
    flex-shrink: 0;
    appearance: none;
    min-height: 36px;
    padding: .35rem .8rem;
    border: 1px solid transparent;
    border-radius: 6px;
    background: linear-gradient(120deg, rgba(60, 255, 218, .96), rgba(105, 224, 255, .92));
    color: rgb(4, 20, 26);
    font: inherit;
    font-size: .8rem;
    font-weight: 700;
    cursor: pointer;
}
.update-notice-dismiss {
    flex-shrink: 0;
    appearance: none;
    background: none;
    border: none;
    min-width: 32px;
    min-height: 32px;
    font-size: 1.1rem;
    color: rgba(232, 255, 251, .6);
    cursor: pointer;
}
.update-notice-action:focus-visible,
.update-notice-dismiss:focus-visible {
    outline: 2px solid rgba(105, 224, 255, .92);
    outline-offset: 2px;
}

/* CLAUDE-LANDING-SONIC-01 - the startup cue's off switch. EXPERIMENTAL.
   Corner-anchored so it takes no room in the entry composition, and quiet
   enough that it reads as a setting rather than an action. Safe-area insets
   because on a notched phone the bottom corners are exactly where the home
   indicator lives. */
.landing-sound-toggle {
    position: fixed;
    right: max(12px, env(safe-area-inset-right));
    bottom: calc(env(safe-area-inset-bottom) + 12px);
    z-index: 5;
    appearance: none;
    /* 40px, not the 24px this glyph wants to be: it is a touch target on a
       phone before it is an icon. */
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(176, 219, 255, .18);
    border-radius: 999px;
    background: rgba(20, 60, 70, .28);
    color: rgba(232, 255, 251, .7);
    font-size: .95rem;
    line-height: 1;
    cursor: pointer;
    opacity: .55;
    transition: opacity 200ms ease, border-color 200ms ease;
}
.landing-sound-toggle:hover,
.landing-sound-toggle:focus-visible {
    opacity: 1;
    border-color: rgba(176, 219, 255, .4);
}
.landing-sound-toggle:focus-visible {
    outline: 2px solid rgba(105, 224, 255, .92);
    outline-offset: 2px;
}
