/* =====================================================================
   PixelOrbit Studio — shared stylesheet
   ---------------------------------------------------------------------
    1. Reset / normalisation
    2. Design tokens
    3. Base styles
    4. Typography
    5. Utilities
    6. Page frame / layout
    7. Header
    8. Navigation
    9. Mobile navigation
   10. Hero
   11. Buttons
   12. Value row
   13. Our Apps
   14. Nebula Notes card
   15. Ideas in Motion
   16. Footer
   17. Accessibility helpers
   18. Responsive breakpoints
   19. Reduced-motion overrides
   20. Nebula Notes product page
   21. Nebula Notes privacy policy page
   22. Terms of Service page
   23. About page
   24. Contact page
   25. Apps page
   26. General privacy policy page
   27. Not found (404)
   ===================================================================== */


/* ---------------------------------------------------------------------
   1. Reset / normalisation
   --------------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  /* The site is dark by design. Declaring it stops Chrome's auto dark mode from
     re-tinting the palette — which inverts white gradient stops and turns the
     "Everyday" fill near-black — and gives form controls and scrollbars the
     correct dark treatment. */
  color-scheme: dark;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Breathing room above in-page anchor targets. */
  scroll-padding-top: 2rem;
}

/* Global content scale. Type, controls, icons and spacing are all sized in rem,
   so this one value tunes the whole UI together — without touching the frame
   width or the artwork, which are set in px and vw. It is scoped to wide
   viewports on purpose: the fluid ramps only reach their rem ceilings on large
   screens, which is where the UI read oversized. Below this width the vw terms
   are in charge and phone sizing stays exactly as it was. A percentage rather
   than a px value keeps the reader's own browser font-size preference intact.
   Raise toward 100% for a larger UI. */
@media (min-width: 900px) {
  html {
    font-size: 90%;
  }
}

body,
h1, h2, h3, p, ul, ol, figure {
  margin: 0;
}

/* <ol> is included so the breadcrumb does not inherit the UA's 40px
   padding-inline-start, which pushes it out of line with the heading below. */
ul, ol {
  padding: 0;
  list-style: none;
}

a {
  color: inherit;
  text-decoration: none;
}

img,
svg {
  display: block;
  max-width: 100%;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

:focus-visible {
  outline: 2px solid var(--color-cyan);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

/* Caret browsing (F7 in Chrome and Edge) places a blinking text caret in
   ordinary page text. Hide it on non-editable content — it inherits, so one
   declaration covers the page — then restore it wherever text can actually be
   typed, so form fields on future pages keep a visible caret. */
:root {
  caret-color: transparent;
}

input,
textarea,
select,
[contenteditable]:not([contenteditable="false"]) {
  caret-color: auto;
}


/* ---------------------------------------------------------------------
   2. Design tokens
   --------------------------------------------------------------------- */

:root {
  /* Surfaces */
  --color-bg-deep: #05070f;
  --color-bg: #070b1a;
  --color-surface: #0a1024;
  --color-surface-soft: #0e1730;
  --color-surface-raised: #101b38;

  /* Text */
  --color-text: #ffffff;
  --color-text-muted: #b6c2dd;
  --color-text-bright: #e3e9f8;

  /* Brand accents */
  --color-indigo: #4c3ff0;
  --color-violet: #7b46f5;
  --color-purple: #a855f7;
  --color-blue: #38bdf8;
  --color-cyan: #67d9f5;
  --color-teal: #2ee6d6;
  --color-pink: #e879f9;
  --color-magenta: #f472d0;

  /* Borders */
  --color-border: rgba(125, 165, 255, 0.14);
  --color-border-soft: rgba(125, 165, 255, 0.09);
  --color-border-bright: rgba(96, 165, 250, 0.42);
  --color-border-accent: rgba(168, 85, 247, 0.55);

  /* Gradients */
  --gradient-primary: linear-gradient(100deg, var(--color-indigo) 0%, var(--color-violet) 100%);

  /* Text gradients are kept horizontal with literal opaque stops: a tilted
     angle makes the painted area depend on the text box's height, which is
     where background-clip: text renders inconsistently between engines. */
  --gradient-brighter: linear-gradient(90deg, #6a5af0 0%, #a855f7 55%, #c45ae4 100%);
  --gradient-everyday: linear-gradient(90deg, #ffffff 0%, #ffffff 38%, #a9c3f0 100%);
  --gradient-orbit: linear-gradient(90deg, #f472d0 0%, #a855f7 38%, #4f7ef8 70%, #22d3ee 100%);
  --gradient-nebula: linear-gradient(90deg, #e879f9 0%, #c46bf6 45%, #a855f7 100%);

  /* Radii */
  --radius-sm: 8px;
  --radius-md: 14px;
  --radius-lg: 20px;
  --radius-xl: 28px;
  --radius-pill: 999px;

  /* Shadows */
  --shadow-soft: 0 18px 40px rgba(2, 6, 20, 0.55);
  --shadow-glow: 0 10px 30px rgba(84, 64, 240, 0.38);
  --shadow-frame: 0 0 0 1px rgba(59, 130, 246, 0.18), 0 0 60px rgba(37, 99, 235, 0.22);

  /* Ring around the value icons — 10% heavier than a hairline. */
  --value-ring-width: 1.1px;

  /* Layout.
     The frame is fluid — it fills the viewport apart from a thin gutter — and
     only stops growing on ultra-wide displays, where unbounded line lengths
     would hurt readability. Type and spacing scale with the viewport so the
     reference's proportions hold as the frame widens. */
  --container-width: 2560px;
  --frame-gutter: clamp(0.5rem, 1.2vw, 1rem);
  --pad-frame: clamp(0.5rem, 1.2vw, 1rem);
  --pad-x: clamp(1.25rem, 3vw, 4rem);
  --pad-x-hero: clamp(1.25rem, 5vw, 6.5rem);
  --pad-x-footer: clamp(1.25rem, 4.6vw, 6rem);
  --pad-x-values: clamp(0.5rem, 1vw, 1.25rem);
  --header-height: clamp(4.5rem, 11vw, 10rem);

  /* Height of the decorative sky backdrop (header + hero + value row). */
  --sky-height: clamp(46rem, 46vw + 40rem, 92rem);

  --transition: 180ms ease;
}


/* ---------------------------------------------------------------------
   3. Base styles
   --------------------------------------------------------------------- */

body {
  min-height: 100vh;
  padding: var(--frame-gutter);
  font-family: "Outfit", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: clamp(1rem, 0.95rem + 0.2vw, 1.0625rem);
  line-height: 1.6;
  color: var(--color-text);
  background-color: var(--color-bg-deep);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}


/* ---------------------------------------------------------------------
   4. Typography
   --------------------------------------------------------------------- */

.section-title {
  font-size: clamp(2rem, 1.3rem + 2.6vw, 4rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
}

.section-lead {
  margin-top: 0.5rem;
  font-size: clamp(1rem, 0.9rem + 0.62vw, 1.5rem);
  color: var(--color-text-muted);
}


/* ---------------------------------------------------------------------
   5. Utilities
   --------------------------------------------------------------------- */

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Lets a <picture> wrap an image without generating a box of its own, so the
   <img> keeps its place in the layout and every existing selector still applies. */
.media {
  display: contents;
}

.skip-link {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 100;
  padding: 0.7rem 1.1rem;
  font-weight: 600;
  color: var(--color-text);
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-bright);
  border-radius: var(--radius-pill);
  transform: translateY(-200%);
  transition: transform var(--transition);
}

.skip-link:focus-visible {
  transform: translateY(0);
}


/* ---------------------------------------------------------------------
   6. Page frame / layout
   --------------------------------------------------------------------- */

.site-frame {
  position: relative;
  isolation: isolate;
  max-width: var(--container-width);
  margin-inline: auto;
  padding: var(--pad-frame);
  overflow: hidden;
  background-color: var(--color-bg);
  border: 1px solid var(--color-border-bright);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-frame);
}

/* Decorative night-sky backdrop behind the header, hero and value row. */
.sky {
  position: absolute;
  inset: 0 0 auto;
  z-index: -2;
  width: 100%;
  height: var(--sky-height);
  object-fit: cover;
  /* Places the galaxy upper-right and the mountains right, as in the reference. */
  object-position: 42% center;
}

/* Blends the artwork into the page background before the Our Apps panel. */
.sky__fade {
  position: absolute;
  inset: 0 0 auto;
  z-index: -1;
  height: var(--sky-height);
  pointer-events: none;
  background:
    linear-gradient(
      to bottom,
      rgba(5, 7, 15, 0.55) 0%,
      rgba(5, 7, 15, 0.12) 16%,
      rgba(7, 11, 26, 0) 52%,
      rgba(7, 11, 26, 0.55) 82%,
      var(--color-bg) 100%
    ),
    /* Localised contrast pad behind the hero copy only. */
    linear-gradient(
      100deg,
      rgba(4, 6, 16, 0.7) 0%,
      rgba(4, 6, 16, 0.34) 38%,
      rgba(4, 6, 16, 0) 62%
    );
}


/* ---------------------------------------------------------------------
   7. Header
   --------------------------------------------------------------------- */

.site-header {
  position: relative;
  display: flex;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
  min-height: var(--header-height);
  padding-inline: var(--pad-x);
}

/* --- Brand lockup: supplied mark + typeset wordmark --- */

.brand {
  display: flex;
  gap: clamp(0.5rem, 1vw, 0.85rem);
  align-items: center;
  flex-shrink: 0;
}

.brand__mark {
  width: auto;
  height: clamp(2.75rem, 7.4vw, 6.5rem);
  filter: drop-shadow(0 4px 18px rgba(124, 92, 245, 0.45));
}

.brand__lockup {
  display: flex;
  flex-direction: column;
  line-height: 1;
}

.brand__name {
  font-size: clamp(1.4rem, 0.85rem + 2.4vw, 2.875rem);
  font-weight: 600;
  letter-spacing: -0.015em;
}

.brand__name-orbit {
  color: var(--color-purple);
}

/* ---------------------------------------------------------------------
   Gradient-filled text
   ---------------------------------------------------------------------
   `inline-block` gives each span a single unfragmented box so the gradient
   paints reliably, and `-webkit-text-fill-color` leaves the `color` above as a
   genuine fallback wherever background-clip: text is unavailable.
   --------------------------------------------------------------------- */

@supports ((background-clip: text) or (-webkit-background-clip: text)) {

  .brand__name-orbit,
  .hero__brighter,
  .hero__everyday,
  .privacy-hero__product,
  .terms-hero__brand,
  .about-hero__brand,
  .contact-hero__brand {
    display: inline-block;
    /* background-clip: text paints only inside the background box, so any glyph
       ink outside it is erased. The tight display line-height makes that box
       shorter than Outfit's ascender-to-descender ink, which shears descenders
       ("g", "y"). Padding grows the box; the matching negative margin keeps the
       line box — and therefore the layout — exactly as it was. */
    padding-block: 0.25em;
    margin-block: -0.25em;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
  }

  .brand__name-orbit     { background-image: var(--gradient-orbit); }
  .hero__brighter        { background-image: var(--gradient-brighter); }
  .hero__everyday        { background-image: var(--gradient-everyday); }
  .privacy-hero__product { background-image: var(--gradient-nebula); }
  .terms-hero__brand      { background-image: var(--gradient-nebula); }
  .about-hero__brand      { background-image: var(--gradient-nebula); }
  .contact-hero__brand    { background-image: var(--gradient-nebula); }
}

.brand__sub {
  margin-top: 0.35em;
  font-size: clamp(0.6rem, 0.45rem + 0.45vw, 0.95rem);
  font-weight: 500;
  letter-spacing: 0.52em;
  text-indent: 0.52em;
  text-transform: uppercase;
  color: var(--color-text);
}


/* ---------------------------------------------------------------------
   8. Navigation (desktop)
   --------------------------------------------------------------------- */

/* Links sit toward the centre, the CTA hugs the right edge — as in the reference. */
.site-nav {
  display: flex;
  flex: 1;
  gap: clamp(1.25rem, 3vw, 3rem);
  align-items: center;
  justify-content: space-between;
  margin-left: clamp(1.5rem, 6vw, 4.5rem);
}

.nav-list {
  display: flex;
  gap: clamp(1.1rem, 2.4vw, 2.4rem);
  align-items: center;
}

.nav-link {
  position: relative;
  display: inline-block;
  padding-block: 0.4rem;
  font-size: clamp(0.95rem, 0.9rem + 0.35vw, 1.3125rem);
  font-weight: 500;
  color: var(--color-text);
  transition: color var(--transition);
}

.nav-link::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  height: 1px;
  background: var(--gradient-orbit);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--transition);
}

.nav-link:hover {
  color: #dce6ff;
}

.nav-link:hover::after,
.nav-link:focus-visible::after,
/* Current page: the same understated underline the header already uses for
   hover and focus, held on rather than animated in. No new visual language. */
.nav-link[aria-current="page"]::after {
  transform: scaleX(1);
}

.nav-cta {
  flex-shrink: 0;
}

.nav-toggle {
  display: none;
}


/* ---------------------------------------------------------------------
   10. Hero
   --------------------------------------------------------------------- */

.hero {
  padding: clamp(1.25rem, 2.4vw, 2.5rem) var(--pad-x-hero) clamp(3rem, 9vw, 9rem);
}

.badge {
  display: inline-block;
  padding: 0.6em 1.35em;
  font-size: clamp(0.8125rem, 0.76rem + 0.4vw, 1.25rem);
  font-weight: 500;
  color: var(--color-text);
  background: rgba(8, 14, 30, 0.55);
  border: 1px solid rgba(45, 212, 191, 0.38);
  border-radius: var(--radius-pill);
  backdrop-filter: blur(4px);
}

.hero__title {
  margin-top: clamp(1.25rem, 3vw, 2.25rem);
  font-size: clamp(2.75rem, 1rem + 7.2vw, 7rem);
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -0.025em;
  /* No text-wrap: balance here. The line breaks are authored with <br>, so
     balancing gains nothing and it fragments the gradient-filled spans below,
     which Chrome then paints incorrectly. */
}

.hero__brighter {
  color: var(--color-purple);
}

.hero__everyday {
  color: #b9cdf3;
}

/* Width is tuned so the copy breaks into the three lines shown in the reference. */
.hero__lead {
  max-width: 33rem;
  margin-top: clamp(1.25rem, 2.6vw, 2.1rem);
  font-size: clamp(1rem, 0.9rem + 0.55vw, 1.5625rem);
  line-height: 1.78;
  color: var(--color-text-bright);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(0.75rem, 1.6vw, 1.25rem);
  margin-top: clamp(1.75rem, 3.8vw, 3rem);
}


/* ---------------------------------------------------------------------
   11. Buttons
   --------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  gap: 0.6em;
  align-items: center;
  justify-content: center;
  min-height: clamp(3rem, 5.4vw, 4.5rem);
  padding: 0.9em 2.4em;
  font-size: clamp(0.9375rem, 0.9rem + 0.45vw, 1.3125rem);
  font-weight: 600;
  line-height: 1.2;
  color: var(--color-text);
  text-align: center;
  /* Keeps the label on one line, so a pair of buttons wraps onto separate rows
     rather than being squeezed narrower than its own text. */
  white-space: nowrap;
  border-radius: var(--radius-pill);
  transition: background-color var(--transition), border-color var(--transition),
              box-shadow var(--transition), filter var(--transition);
}

.btn__arrow {
  width: 1.15em;
  height: 1.15em;
  flex-shrink: 0;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.btn--primary {
  background-image: var(--gradient-primary);
  border: 1px solid rgba(163, 148, 255, 0.5);
  box-shadow: var(--shadow-glow);
}

.btn--primary:hover {
  filter: brightness(1.12);
  box-shadow: 0 12px 34px rgba(84, 64, 240, 0.5);
}

.btn--outline {
  background-color: rgba(10, 16, 36, 0.55);
  border: 1px solid var(--color-border-accent);
  backdrop-filter: blur(4px);
}

.btn--outline:hover {
  border-color: rgba(196, 132, 252, 0.9);
  box-shadow: 0 0 22px rgba(168, 85, 247, 0.28);
}

/* Header CTA sits slightly tighter than the hero calls to action. */
.nav-cta {
  min-height: clamp(3rem, 4.2vw, 3.5rem);
  padding-inline: clamp(1.25rem, 3vw, 2.75rem);
}


/* ---------------------------------------------------------------------
   12. Value row
   --------------------------------------------------------------------- */

.values {
  padding: clamp(1rem, 2.4vw, 2.4rem) var(--pad-x-values) clamp(2.5rem, 6vw, 6rem);
}

.values__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(1.5rem, 3vw, 2.25rem) clamp(0.75rem, 2vw, 1.5rem);
}

.value {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.value__icon {
  display: grid;
  place-items: center;
  width: clamp(3.75rem, 7.5vw, 6.75rem);
  aspect-ratio: 1;
  margin-bottom: clamp(0.9rem, 2vw, 1.5rem);
  border-radius: 50%;
  background: radial-gradient(circle at 50% 40%, var(--value-tint) 0%, rgba(8, 14, 32, 0.82) 78%);
  /* The ring is a box-shadow rather than a border: Chrome snaps border-width to
     whole device pixels, which rounds a 1.1px border back to exactly 1px. A
     shadow spread is antialiased, so the fractional width survives. */
  box-shadow: 0 0 0 var(--value-ring-width) var(--value-ring);
  transition: box-shadow var(--transition);
}

/* Decorative hover lift, matching the outline buttons: the ring takes the item's
   own accent and picks up a restrained glow. Purely presentational — the value
   items stay non-interactive, so no pointer cursor and nothing to activate. */
.value:hover .value__icon {
  box-shadow:
    0 0 0 var(--value-ring-width) currentColor,
    0 0 22px var(--value-glow);
}

.value__icon svg {
  width: 46%;
  height: 46%;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.value__icon--bolt   { --value-tint: rgba(34, 211, 238, 0.17);  --value-ring: rgba(34, 211, 238, 0.22);  --value-glow: rgba(56, 189, 248, 0.3);  color: var(--color-blue); }
.value__icon--heart  { --value-tint: rgba(232, 121, 249, 0.17); --value-ring: rgba(232, 121, 249, 0.22); --value-glow: rgba(232, 121, 249, 0.3); color: var(--color-pink); }
.value__icon--shield { --value-tint: rgba(56, 189, 248, 0.17);  --value-ring: rgba(56, 189, 248, 0.22);  --value-glow: rgba(103, 217, 245, 0.3); color: var(--color-cyan); }
.value__icon--leaf   { --value-tint: rgba(45, 212, 191, 0.17);  --value-ring: rgba(45, 212, 191, 0.22);  --value-glow: rgba(46, 230, 214, 0.3);  color: var(--color-teal); }

.value__title {
  font-size: clamp(0.95rem, 0.85rem + 0.55vw, 1.4375rem);
  font-weight: 700;
  line-height: 1.3;
}

.value__text {
  max-width: 15rem;
  margin-top: 0.45rem;
  font-size: clamp(0.875rem, 0.82rem + 0.45vw, 1.25rem);
  line-height: 1.5;
  color: var(--color-text-muted);
  text-wrap: balance;
}


/* ---------------------------------------------------------------------
   13. Our Apps
   --------------------------------------------------------------------- */

.apps {
  padding: clamp(1.75rem, 3vw, 3rem) var(--pad-x);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

/* Link on to the dedicated Apps page.

   Placed after the cards and left-aligned rather than centred or floated up
   beside the heading. A 'view all' beside a section heading is a shortcut for
   a row that is showing a subset of many items; this section shows its cards
   in full, so the useful moment for the link is once the reader has seen them.
   The left edge is the one the heading, the lead and the card already sit on,
   so it joins the section's existing rhythm instead of starting a new axis.

   Outline, not primary: the card's own Learn More stays the single primary
   action here, and the two never read as competing for the same click. */
.apps__all {
  margin-top: clamp(1.25rem, 2.4vw, 2rem);
}


/* ---------------------------------------------------------------------
   14. Nebula Notes card
   --------------------------------------------------------------------- */

.app-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: clamp(1.25rem, 2.6vw, 2.25rem);
  align-items: center;
  margin-top: clamp(1.75rem, 3.2vw, 2.5rem);
  padding: clamp(1.25rem, 2.2vw, 2.25rem);
  background-color: var(--color-surface-soft);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition: border-color var(--transition), box-shadow var(--transition);
}

.app-card:hover,
.app-card:focus-within {
  border-color: var(--color-border-bright);
  box-shadow: 0 0 28px rgba(59, 130, 246, 0.14);
}

.app-card__icon {
  width: clamp(5.5rem, 13vw, 12.5rem);
  height: auto;
  border-radius: 22%;
  /* Reproduces the reference ring; the supplied artwork is unmodified. */
  box-shadow: 0 0 0 1.5px rgba(244, 114, 208, 0.75), 0 10px 26px rgba(8, 10, 30, 0.6);
}

.app-card__title {
  font-size: clamp(1.25rem, 0.95rem + 1.4vw, 2.75rem);
  font-weight: 700;
  line-height: 1.2;
}

.app-card__slogan {
  margin-top: 0.35rem;
  font-size: clamp(0.95rem, 0.88rem + 0.5vw, 1.4375rem);
  font-weight: 600;
  color: var(--color-magenta);
}

.app-card__text {
  max-width: 33rem;
  margin-top: 0.6rem;
  font-size: clamp(0.9rem, 0.85rem + 0.45vw, 1.25rem);
  line-height: 1.55;
  color: var(--color-text-muted);
  text-wrap: pretty;
}

.app-card__cta {
  justify-self: end;
}


/* ---------------------------------------------------------------------
   15. Ideas in Motion
   --------------------------------------------------------------------- */

.ideas {
  margin-top: clamp(1rem, 2vw, 1.5rem);
  overflow: hidden;
  background-color: var(--color-surface);
  /* Plain url() first: it is what engines without image-set() use, and it is
     also the no-WebP path. The image-set() below then upgrades both. */
  background-image: url("../images/ideas-in-motion-background-1280.jpg");
  background-image: image-set(
    url("../images/ideas-in-motion-background-1280.webp") type("image/webp"),
    url("../images/ideas-in-motion-background-1280.jpg") type("image/jpeg")
  );
  background-repeat: no-repeat;
  background-position: center center;
  background-size: cover;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

/* The band spans the full frame width, so step the source up with the viewport.
   A no-WebP engine ignores these and keeps the JPEG declared above. */
@media (min-width: 1100px) {
  .ideas {
    background-image: image-set(
      url("../images/ideas-in-motion-background-1920.webp") type("image/webp")
    );
  }
}

@media (min-width: 1750px) {
  .ideas {
    background-image: image-set(
      url("../images/ideas-in-motion-background-2560.webp") type("image/webp")
    );
  }
}

.ideas__inner {
  /* The band's width tracks the frame but its height is content-driven, so on
     wide screens it flattens out and background-size: cover crops away most of
     the artwork's height. This floor holds it open so more of the scene stays in
     frame — a deliberate step short of the reference's ~4.5 ratio, which would
     leave too much empty sky around the copy at this type scale.
     It is inert on narrow screens, where the stacked content is already taller. */
  min-height: min(16vw, 34rem);

  display: flex;
  flex-wrap: wrap;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: center;
  justify-content: space-between;
  padding: clamp(2rem, 4.5vw, 4.25rem) clamp(1.5rem, 6vw, 7.5rem);
  /* Just enough lift for text contrast; the artwork stays readable. */
  background: linear-gradient(
    100deg,
    rgba(6, 8, 24, 0.72) 0%,
    rgba(6, 8, 24, 0.45) 45%,
    rgba(6, 8, 24, 0.08) 78%,
    rgba(6, 8, 24, 0) 100%
  );
}

.ideas__body {
  max-width: 34rem;
}

.ideas__title {
  font-size: clamp(1.75rem, 1.35rem + 1.6vw, 3rem);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
}

.ideas__text {
  margin-top: clamp(0.75rem, 1.5vw, 1.1rem);
  font-size: clamp(0.95rem, 0.89rem + 0.45vw, 1.375rem);
  line-height: 1.65;
  color: var(--color-text-bright);
  text-wrap: pretty;
}

.ideas__cta {
  flex-shrink: 0;
}


/* ---------------------------------------------------------------------
   16. Footer
   --------------------------------------------------------------------- */

.site-footer {
  margin-top: clamp(1rem, 2vw, 1.5rem);
  padding: clamp(1.5rem, 2.4vw, 2.5rem) var(--pad-x-footer) clamp(1rem, 2vw, 1.75rem);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.footer__top {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr) minmax(0, 0.9fr);
  gap: clamp(1.75rem, 4vw, 3rem);
}

.brand--footer .brand__mark {
  height: clamp(2.4rem, 3.6vw, 4rem);
}

.footer__tagline {
  margin-top: clamp(1rem, 2vw, 1.5rem);
  font-size: clamp(0.9rem, 0.85rem + 0.45vw, 1.25rem);
  color: #dbe3f5;
}

.footer__about {
  max-width: 30rem;
  margin-top: 0.35rem;
  font-size: clamp(0.9rem, 0.85rem + 0.45vw, 1.25rem);
  line-height: 1.6;
  color: var(--color-text-muted);
}

.footer__heading {
  font-size: clamp(1rem, 0.92rem + 0.55vw, 1.5rem);
  font-weight: 700;
}

.footer__list {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  margin-top: clamp(1rem, 2vw, 1.5rem);
}

.footer__list a {
  display: inline-block;
  padding-block: 0.15rem;
  color: var(--color-text-muted);
  transition: color var(--transition);
}

.footer__list a:hover {
  color: var(--color-text);
}

.social {
  /* The tap target is larger than the glyph, so each icon sits inset from the
     edge of its box. Pulling the row left by exactly that inset lines the
     glyphs up with the "Follow" heading without shrinking the target. */
  --social-box: clamp(2.75rem, 3.4vw, 3.25rem);
  --social-glyph: clamp(1.5rem, 1.9vw, 1.85rem);

  display: flex;
  /* Six icons overflow the narrow Follow column at mid widths, so let them
     wrap onto a second row rather than pushing past it. */
  flex-wrap: wrap;
  gap: clamp(0.5rem, 1.4vw, 1rem);
  margin-top: clamp(1rem, 2vw, 1.5rem);
  margin-left: calc((var(--social-glyph) - var(--social-box)) / 2);
}

.social__link {
  display: grid;
  place-items: center;
  width: var(--social-box);
  height: var(--social-box);
  color: var(--color-text);
  border-radius: var(--radius-sm);
  opacity: 0.85;
  transition: opacity var(--transition), background-color var(--transition);
}

.social__link svg {
  width: var(--social-glyph);
  height: var(--social-glyph);
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.social__link:hover {
  opacity: 1;
  background-color: rgba(125, 165, 255, 0.1);
}

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem clamp(1.5rem, 3vw, 2.5rem);
  align-items: center;
  justify-content: space-between;
  margin-top: clamp(1.5rem, 2.6vw, 2rem);
  padding-top: clamp(1.1rem, 2vw, 1.6rem);
  border-top: 1px solid var(--color-border-soft);
}

.footer__copy,
.footer__legal a {
  font-size: clamp(0.85rem, 0.81rem + 0.4vw, 1.1875rem);
  color: var(--color-text-muted);
}

.footer__legal {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem clamp(1.25rem, 2.6vw, 2.25rem);
}

.footer__legal a {
  display: inline-block;
  padding-block: 0.15rem;
  transition: color var(--transition);
}

.footer__legal a:hover {
  color: var(--color-text);
}


/* ---------------------------------------------------------------------
   18. Responsive breakpoints
   --------------------------------------------------------------------- */

/* --- Tablet and below: mobile navigation, 2 x 2 value grid --- */
@media (max-width: 900px) {

  /* 9. Mobile navigation */
  .nav-toggle {
    display: grid;
    place-items: center;
    width: 2.75rem;
    height: 2.75rem;
    border: 1px solid var(--color-border-bright);
    border-radius: var(--radius-md);
    background-color: rgba(10, 16, 36, 0.55);
  }

  .nav-toggle__bars {
    display: flex;
    flex-direction: column;
    gap: 5px;
    width: 1.25rem;
  }

  .nav-toggle__bars span {
    height: 2px;
    background-color: var(--color-text);
    border-radius: 2px;
    transition: transform var(--transition), opacity var(--transition);
  }

  .nav-toggle[aria-expanded="true"] .nav-toggle__bars span:nth-child(1) {
    transform: translateY(7px) rotate(45deg);
  }

  .nav-toggle[aria-expanded="true"] .nav-toggle__bars span:nth-child(2) {
    opacity: 0;
  }

  .nav-toggle[aria-expanded="true"] .nav-toggle__bars span:nth-child(3) {
    transform: translateY(-7px) rotate(-45deg);
  }

  .site-nav {
    position: absolute;
    top: calc(100% - 0.25rem);
    right: var(--pad-x);
    left: var(--pad-x);
    z-index: 20;
    flex-direction: column;
    gap: 0.35rem;
    align-items: stretch;
    margin-left: 0;
    padding: 0.85rem;
    background-color: rgba(10, 16, 36, 0.96);
    border: 1px solid var(--color-border-bright);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-soft);
    backdrop-filter: blur(10px);
  }

  .site-nav:not(.is-open) {
    display: none;
  }

  .nav-list {
    flex-direction: column;
    gap: 0.15rem;
    align-items: stretch;
  }

  .nav-link {
    padding: 0.75rem 0.9rem;
    border-radius: var(--radius-md);
  }

  .nav-link:hover {
    background-color: rgba(125, 165, 255, 0.08);
  }

  .nav-link::after {
    display: none;
  }

  .nav-cta {
    margin-top: 0.5rem;
  }

  /* Value grid folds to 2 x 2 */
  .values__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* Nebula Notes card: icon + copy, CTA drops to its own row */
  .app-card {
    grid-template-columns: auto minmax(0, 1fr);
  }

  .app-card__cta {
    grid-column: 1 / -1;
    justify-self: start;
  }

  /* Narrower viewports let the copy reach the bright side of the artwork,
     so the contrast pad has to carry further across. */
  .ideas__inner {
    background: linear-gradient(
      105deg,
      rgba(6, 8, 24, 0.8) 0%,
      rgba(6, 8, 24, 0.62) 58%,
      rgba(6, 8, 24, 0.28) 100%
    );
  }

  /* Footer folds to two columns */
  .footer__top {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .footer__brand {
    grid-column: 1 / -1;
  }
}

/* --- Phones --- */
@media (max-width: 640px) {

  :root {
    --sky-height: clamp(34rem, 150vw + 8rem, 52rem);
  }

  /* Keep the galaxy and mountains in frame on a much taller crop. */
  .sky {
    object-position: 72% center;
  }

  /* On phones the copy spans the full width, so the contrast pad has to be
     vertical. It lifts the text band only and releases over the reflection. */
  .sky__fade {
    background: linear-gradient(
      to bottom,
      rgba(5, 7, 15, 0.72) 0%,
      rgba(5, 7, 15, 0.64) 48%,
      rgba(5, 7, 15, 0.22) 72%,
      rgba(7, 11, 26, 0.6) 90%,
      var(--color-bg) 100%
    );
  }

  .hero__title {
    line-height: 1.1;
  }

  .hero__actions .btn {
    flex: 1 1 12rem;
  }

  .values__grid {
    gap: 1.75rem 1rem;
  }

  /* Nebula Notes card stacks completely */
  .app-card {
    grid-template-columns: minmax(0, 1fr);
    justify-items: start;
    text-align: left;
  }

  .app-card__cta {
    width: 100%;
  }

  .ideas__inner {
    align-items: flex-start;
  }

  .ideas__cta {
    width: 100%;
  }

  .footer__top {
    grid-template-columns: minmax(0, 1fr);
  }

  .footer__bottom {
    justify-content: flex-start;
  }
}

/* --- Very narrow phones: stack the value row --- */
@media (max-width: 380px) {
  .values__grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .value__text {
    max-width: none;
  }
}


/* ---------------------------------------------------------------------
   19. Reduced-motion overrides
   --------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}


/* =========================================================
   20. Nebula Notes Product Page
   ---------------------------------------------------------
   Scoped to .page-product or to product-only classes, so nothing
   here can reach the homepage. Reuses the shared frame, header,
   buttons, value row and footer; only product-specific pieces
   are defined below.

   20.1  Product page base
   20.2  Product hero
   20.3  Featured App badge
   20.4  Product identity
   20.5  Hero phone and decoration
   20.6  Product feature icons
   20.7  More Than Notes
   20.8  Screenshot gallery
   20.9  Download CTA
   20.10 Product responsive behaviour
   ========================================================= */


/* --- 20.1 Product page base ------------------------------- */

/* The product hero sits over a wider, shorter slice of artwork than the
   homepage sky, so the height is retuned rather than inherited. */
.page-product {
  --sky-height: clamp(34rem, 34vw + 22rem, 62rem);
}

.sky--product {
  object-position: center 62%;
}

/* Keeps the copy side dark enough for contrast while leaving the nebula
   and mountains on the right clearly visible. */
.sky__fade--product {
  background:
    linear-gradient(
      to bottom,
      rgba(5, 7, 15, 0.62) 0%,
      rgba(5, 7, 15, 0.3) 22%,
      rgba(7, 11, 26, 0.18) 55%,
      rgba(7, 11, 26, 0.72) 86%,
      var(--color-bg) 100%
    ),
    linear-gradient(
      100deg,
      rgba(4, 6, 16, 0.82) 0%,
      rgba(4, 6, 16, 0.5) 40%,
      rgba(4, 6, 16, 0) 68%
    );
}


/* --- 20.2 Product hero ------------------------------------ */

.product-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 4rem);
  align-items: center;
  padding: clamp(1.25rem, 2.4vw, 2.5rem) var(--pad-x-hero) clamp(2rem, 5vw, 4.5rem);
}

.product-hero__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}


/* --- 20.3 Featured App badge ------------------------------ */

.badge--featured {
  font-weight: 600;
  color: var(--color-magenta);
  background: rgba(12, 8, 30, 0.6);
  border-color: var(--color-border-accent);
  transition: color var(--transition), border-color var(--transition),
              box-shadow var(--transition);
}

/* Decorative lift only, in the same language as the outline buttons. The badge
   is a label, not a control, so it gains no pointer cursor and nothing to
   activate. */
.badge--featured:hover {
  color: var(--color-pink);
  border-color: rgba(244, 114, 208, 0.9);
  box-shadow: 0 0 22px rgba(244, 114, 208, 0.26);
}


/* --- 20.4 Product identity -------------------------------- */

.product-icon {
  width: clamp(5rem, 16.6vw, 18rem);
  height: auto;
  margin-top: clamp(1.1rem, 2.4vw, 1.9rem);
  border-radius: 22%;
  /* Reproduces the reference's cyan-to-pink ring; the artwork is untouched. */
  box-shadow:
    0 0 0 1.5px var(--color-cyan),
    0 0 0 3px rgba(244, 114, 208, 0.75),
    0 12px 34px rgba(8, 10, 30, 0.6);
}

.product-title {
  margin-top: clamp(0.85rem, 2vw, 1.5rem);
  font-size: clamp(2.25rem, 1rem + 4.6vw, 4.45rem);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.025em;
}

.product-subtitle {
  margin-top: clamp(0.4rem, 1vw, 0.7rem);
  font-size: clamp(1.05rem, 0.85rem + 1.15vw, 1.91rem);
  font-weight: 600;
  color: var(--color-magenta);
}

.product-lead {
  max-width: 33rem;
  margin-top: clamp(0.9rem, 2vw, 1.5rem);
  font-size: clamp(1rem, 0.9rem + 0.55vw, 1.3125rem);
  line-height: 1.65;
  color: var(--color-text-bright);
  text-wrap: pretty;
}

/* The supplied master is a square canvas with the badge centred in wide
   transparent margins; the derivative is trimmed to that content box, so the
   artwork's own edge is the link's edge and it aligns with the copy above. */
.play-badge {
  display: block;
  width: clamp(10.5rem, 30vw, 32rem);
  margin-top: clamp(1.25rem, 2.6vw, 2rem);
  border-radius: var(--radius-md);
  transition: filter var(--transition), box-shadow var(--transition);
}

.play-badge img {
  width: 100%;
  height: auto;
}

.play-badge:hover {
  filter: brightness(1.08);
  box-shadow: 0 0 24px rgba(125, 165, 255, 0.22);
}

.product-more {
  display: inline-flex;
  gap: 0.45em;
  align-items: center;
  margin-top: clamp(1rem, 2.2vw, 1.6rem);
  padding-block: 0.35rem;
  font-size: clamp(0.95rem, 0.88rem + 0.4vw, 1.1875rem);
  font-weight: 600;
  color: var(--color-magenta);
  transition: color var(--transition);
}

.product-more__arrow {
  width: 1.05em;
  height: 1.05em;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.product-more:hover {
  color: var(--color-pink);
}


/* --- 20.5 Hero phone and decoration ----------------------- */

.product-hero__visual {
  --aside-w: clamp(4.25rem, 10vw, 13rem);
  --left-w: clamp(3.25rem, 8vw, 10rem);
  /* The phone gives up a little width so the enlarged decorations fit beside it
     without being clipped at the frame edge. */
  --phone-w: clamp(11rem, 26vw, 28rem);
  --decor-gap: clamp(0.5rem, 1.1vw, 1.75rem);

  /* The phone centres, and the decorations are anchored to ITS edges rather
     than the column's — so they stay beside the device however wide the column
     grows. They are positioned rather than in flow: in flow they consumed row
     width and pushed the right-hand group past the frame edge. */
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}

.product-phone {
  /* Same variable the decoration anchors compute from, so they cannot drift. */
  width: var(--phone-w);
  height: auto;
  filter: drop-shadow(0 26px 60px rgba(4, 6, 20, 0.75));
}

/* Decorative script line from the reference. The site ships a single family,
   so this is Outfit italic rather than a handwriting face. */
/* The celestial trio beside the phone — constellation, script line and the
   trailing sparkle — stacked as in the reference. The phone is left-aligned in
   its column so this occupies the slack on the right. */
.product-aside {
  position: absolute;
  top: 4%;
  left: calc(50% + var(--phone-w) / 2 + var(--decor-gap));
  display: flex;
  flex: none;
  flex-direction: column;
  align-items: center;
  gap: clamp(0.6rem, 2.2vw, 2.5rem);
  width: var(--aside-w);
  pointer-events: none;
}

.product-script {
  flex: none;
}

.product-script {
  font-family: "Caveat", "Segoe Script", "Bradley Hand", cursive;
  /* Sized from the column it has to fit inside, not from the viewport: on a
     viewport-based ramp the longest word outgrew the aside and overflowed it,
     pushing past the frame edge and getting clipped. */
  max-width: 100%;
  font-size: clamp(1rem, calc(var(--aside-w) / 3.7), 3.25rem);
  font-weight: 600;
  line-height: 1.12;
  text-align: center;
  color: #b3c2f7;
  text-shadow: 0 0 16px rgba(130, 150, 255, 0.5);
}

/* The SVGs carry real width/height attributes and an explicit aspect-ratio.
   With only a viewBox and `height: auto`, the height is derived from a width
   that a column flex container may not have resolved yet, and the element can
   collapse to zero — which hid this one while its siblings still painted.
   The padded viewBox also keeps the dots' glow from clipping at the edge. */
/* Both dimensions are stated outright, in the same absolute unit the aside
   uses. Nothing is left to be inferred from a percentage width, an `auto`
   height or an aspect-ratio — the paths through which this element was
   collapsing to nothing while its siblings still painted. */
/* `flex: none` matters here: .product-aside is a COLUMN flex container, so the
   default flex-shrink: 1 acts on height. The constellation is the shortest item
   in that column, so it is the first to be squeezed — which is why it vanished
   while the taller script and sparkle kept painting. */
.product-constellation {
  flex: none;
  width: var(--aside-w);
  height: calc(var(--aside-w) * 72 / 96);
  overflow: visible;
}

/* The second constellation sits between the copy and the phone. The frame
   clips any overhang. */
/* Mirrors the aside on the other side of the phone, riding high as in the
   reference, and sits in the column gap rather than out at the far edge. */
.product-constellation--left {
  position: absolute;
  top: 4%;
  right: calc(50% + var(--phone-w) / 2 + var(--decor-gap));
  width: var(--left-w);
  height: calc(var(--left-w) * 80 / 86);
  pointer-events: none;
}

/* The joining lines must stay unfilled, or each closed path paints as a solid
   shape instead of a constellation. */
/* non-scaling-stroke keeps the joining lines at a real 1.2px however far the
   viewBox is scaled down; without it they thin to sub-pixel on narrow screens
   and fade out against the dark backdrop. */
.product-constellation path {
  fill: none;
  stroke: rgba(255, 255, 255, 0.62);
  stroke-width: 1.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.product-constellation circle {
  fill: #ffffff;
  stroke: none;
  filter: drop-shadow(0 0 3px rgba(255, 255, 255, 0.95));
}

.product-spark {
  flex: none;
  width: calc(var(--aside-w) * 0.74);
  height: calc(var(--aside-w) * 0.74 * 120 / 81);
  overflow: visible;
}

.product-spark__star {
  fill: #f8c944;
  stroke: none;
  filter: drop-shadow(0 0 6px rgba(248, 201, 68, 0.7));
}

.product-spark__trail {
  fill: none;
  stroke: rgba(255, 255, 255, 0.8);
  stroke-width: 1.6;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

.product-spark__dot {
  fill: #ffffff;
  stroke: none;
  filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.9));
}


/* --- 20.6 Product feature icons --------------------------- */
/* Extends the shared .value__icon set with this page's accents. */

.value__icon--pen    { --value-tint: rgba(232, 121, 249, 0.17); --value-ring: rgba(232, 121, 249, 0.24); --value-glow: rgba(232, 121, 249, 0.3); color: var(--color-pink); }
.value__icon--folder { --value-tint: rgba(56, 189, 248, 0.17);  --value-ring: rgba(56, 189, 248, 0.24);  --value-glow: rgba(103, 217, 245, 0.3); color: var(--color-blue); }
.value__icon--guard  { --value-tint: rgba(232, 121, 249, 0.17); --value-ring: rgba(232, 121, 249, 0.24); --value-glow: rgba(232, 121, 249, 0.3); color: var(--color-pink); }
.value__icon--moon   { --value-tint: rgba(56, 189, 248, 0.17);  --value-ring: rgba(56, 189, 248, 0.24);  --value-glow: rgba(103, 217, 245, 0.3); color: var(--color-blue); }


/* --- 20.7 More Than Notes --------------------------------- */

.details {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: center;
  padding: clamp(1.75rem, 3.4vw, 3.25rem) var(--pad-x);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.details__title {
  font-size: clamp(1.75rem, 1.1rem + 2.4vw, 3rem);
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.02em;
}

.details__title-accent {
  color: var(--color-magenta);
}

.details__body {
  max-width: 30rem;
  margin-top: clamp(0.9rem, 2vw, 1.4rem);
  font-size: clamp(0.95rem, 0.89rem + 0.45vw, 1.25rem);
  line-height: 1.65;
  color: var(--color-text-bright);
  text-wrap: pretty;
}

.details__list {
  display: flex;
  flex-direction: column;
  gap: clamp(0.7rem, 1.5vw, 1.15rem);
}

.details__list li {
  display: flex;
  gap: clamp(0.7rem, 1.4vw, 1rem);
  align-items: flex-start;
  font-size: clamp(0.9rem, 0.86rem + 0.4vw, 1.1875rem);
  line-height: 1.45;
  color: var(--color-text-bright);
}

.details__list svg {
  width: clamp(1.15rem, 1.5vw, 1.5rem);
  height: clamp(1.15rem, 1.5vw, 1.5rem);
  flex-shrink: 0;
  margin-top: 0.1em;
  fill: none;
  stroke: var(--color-magenta);
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}


/* --- 20.8 Screenshot gallery ------------------------------ */

.shots {
  margin-top: clamp(1rem, 2vw, 1.5rem);
  padding: clamp(1.75rem, 3.4vw, 3.25rem) var(--pad-x);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.shots__track {
  display: grid;
  /* One card per column: the whole gallery reads in a single row, and at this
     width each card is the same size it was when there were six across a
     narrower track. */
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: clamp(0.6rem, 1.2vw, 1.15rem);
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
}

/* The <picture> is the card itself — deliberately not display:contents,
   which stops Chromium from ever loading a lazy image inside it. */
.shot {
  display: block;
  overflow: hidden;
  background-color: var(--color-surface-soft);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: 0 10px 30px rgba(4, 6, 20, 0.45);
}

.shot img {
  width: 100%;
  height: auto;
  /* Marketing artwork is final: show the whole card, never crop or stretch. */
  object-fit: contain;
}


/* --- 20.9 Download CTA ------------------------------------ */

.download {
  padding: clamp(2rem, 4vw, 3.5rem) var(--pad-x);
  text-align: center;
}

.download__cta {
  width: min(100%, 44rem);
  min-height: clamp(3.25rem, 6vw, 5.4rem);
  gap: clamp(0.6rem, 1.2vw, 1rem);
  padding-inline: clamp(1.25rem, 2.4vw, 2.25rem);
}

/* Official Play mark, cropped from the supplied badge rather than redrawn. */
.download__play {
  width: clamp(1.15rem, 1.6vw, 1.6rem);
  height: auto;
  flex-shrink: 0;
}

.download__cta span {
  flex: 1;
}


/* --- 20.10 Product responsive behaviour ------------------- */

/* All seven across only while the cards stay legible. Below that, four — which
   lays the seven out as a full row of four above a row of three. Three columns
   would leave a single card alone on a third row, which reads as a mistake
   rather than as a gallery. */
@media (max-width: 1399px) {
  .shots__track {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: clamp(0.75rem, 1.8vw, 1.25rem);
  }
}

@media (max-width: 900px) {
  .product-hero {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(1.75rem, 5vw, 3rem);
  }

  .product-hero__copy {
    align-items: center;
    text-align: center;
  }

  /* Wherever the hero is stacked, the phone centres in the full width at its
     natural size and the decoration sits beneath it as a plain centred row.
     Keeping it out of absolute positioning means nothing reserves space from
     the phone, nothing can overlap, and no item can be shrunk away. */
  .product-hero__visual {
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: clamp(1rem, 4vw, 1.75rem);
    padding-right: 0;
  }

  .product-aside {
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    width: 100%;
    gap: clamp(0.75rem, 4vw, 2rem);
  }

  .product-script {
    font-size: clamp(1.1rem, 3vw, 1.75rem);
  }

  /* In the stacked layout this one has no gap to sit in — it would float loose
     at the far left, and the row beneath the phone already carries a
     constellation. */
  .product-constellation--left {
    display: none;
  }

  .product-lead {
    max-width: 34rem;
  }

  .details {
    grid-template-columns: minmax(0, 1fr);
  }

  .details__body {
    max-width: none;
  }
}

/* Phones: a swipeable gallery instead of an unreadable grid. */
@media (max-width: 700px) {
  .shots__track {
    display: flex;
    gap: 0.85rem;
    /* Full-bleed to the panel edge so the next card peeks in as an affordance. */
    margin-inline: calc(var(--pad-x) * -1);
    padding-inline: var(--pad-x);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--pad-x);
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
  }

  .shots__track > li {
    flex: 0 0 min(62vw, 15rem);
    scroll-snap-align: start;
  }

}



/* =========================================================
   21. Nebula Notes Privacy Policy Page
   ---------------------------------------------------------
   Scoped to .page-privacy, or to class names used on that
   page alone, so the homepage and the product page are
   untouched.

   21.1  Privacy page base
   21.2  Breadcrumb
   21.3  Policy hero
   21.4  Policy panel
   21.5  Policy cards
   21.6  Reassurance panel
   21.7  Review status and document details
   21.8  Policy dialogs
   21.9  Policy dialog content
   21.10 Privacy responsive behaviour
   ========================================================= */


/* --- 21.1 Privacy page base -------------------------------- */

/* The artwork is 3:2 and object-fit: cover is width-constrained here, so the
   share of the picture that survives is set purely by the band's own aspect
   ratio. The reference band is a shade under 2:1, which shows a little over
   three-quarters of the image — mountains, lake and tree line, not just the
   sky. 51vw holds that ratio as the frame widens, and the cap matches the
   2560px container so the proportion survives on ultra-wide displays. Below
   ~700px the floor takes over: a band half the viewport wide would be too
   shallow to sit the title in. */
.page-privacy {
  --sky-height: clamp(22rem, 51vw, 90rem);
}

.sky--privacy {
  object-position: center 48%;
}

/* Darkens the left, where the breadcrumb and title sit, and blends the
   artwork into the page before the policy panel begins. */
.sky__fade--privacy {
  background:
    linear-gradient(
      to bottom,
      rgba(5, 7, 15, 0.6) 0%,
      rgba(5, 7, 15, 0.2) 24%,
      rgba(7, 11, 26, 0.16) 58%,
      rgba(7, 11, 26, 0.74) 88%,
      var(--color-bg) 100%
    ),
    linear-gradient(
      100deg,
      rgba(4, 6, 16, 0.86) 0%,
      rgba(4, 6, 16, 0.55) 38%,
      rgba(4, 6, 16, 0) 66%
    );
}


/* --- 21.2 Breadcrumb --------------------------------------- */

.breadcrumb__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35em clamp(0.6rem, 1.1vw, 1rem);
  font-size: clamp(0.9rem, 0.85rem + 0.45vw, 1.25rem);
  color: var(--color-text-muted);
}

.breadcrumb__list li {
  display: flex;
  align-items: center;
  gap: clamp(0.6rem, 1.1vw, 1rem);
}

/* Chevron separators are decorative, so they are drawn rather than typed:
   a border glyph never reaches the accessibility tree or the clipboard. */
.breadcrumb__list li + li::before {
  content: "";
  width: 0.42em;
  height: 0.42em;
  border-top: 2px solid currentColor;
  border-right: 2px solid currentColor;
  opacity: 0.65;
  transform: rotate(45deg);
}

.breadcrumb__list a {
  transition: color var(--transition);
}

.breadcrumb__list a:hover {
  color: var(--color-text);
}

.breadcrumb__list [aria-current="page"] {
  color: var(--color-text);
}


/* --- 21.3 Policy hero -------------------------------------- */

/* --pad-x, not the deeper --pad-x-hero the other two pages use: this hero's
   breadcrumb, title and date have to line up with the header's brand and with
   the policy panel's contents below, all of which are inset by --pad-x.

   The min-height makes the hero fill whatever the backdrop does not: the band
   the reader sees ends where the policy panel's opaque background begins, so
   without this the band would stop growing once the type hit its clamp
   ceilings and the artwork would be squeezed into an ever-thinner strip.
   The deeper bottom padding seats the type slightly above centre, as in the
   reference. */
.privacy-hero {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: calc(var(--sky-height) - var(--header-height) - var(--pad-frame));
  padding: clamp(1.25rem, 2.4vw, 2.5rem) var(--pad-x) clamp(2.5rem, 6vw, 6rem);
}

/* Optical alignment. Outfit's left side bearing is about 0.057em, so at the
   title's size the ink starts ~5px inside its box while the breadcrumb and the
   date above and below it start ~1px in — geometrically flush, visually
   indented. The em-based pull cancels the difference and keeps cancelling it as
   the title scales. */
.privacy-hero__title {
  margin-left: -0.045em;
  margin-top: clamp(1rem, 2.4vw, 2rem);
  font-size: clamp(2.5rem, 1rem + 6.2vw, 6rem);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.025em;
}

/* The product name is the second line of the same heading, not a separate
   one: it reads as a single title to assistive technology. */
.privacy-hero__product {
  display: block;
  color: var(--color-pink);
}

.privacy-hero__updated {
  margin-top: clamp(1.1rem, 2.4vw, 2rem);
  font-size: clamp(1rem, 0.9rem + 0.55vw, 1.5rem);
  color: var(--color-text-bright);
}

/* Jump to the policy.
   Hidden by default and revealed only where it earns its place. The backdrop is
   51vw tall, so the policy panel starts roughly 0.51 * viewport-width down the
   page; it therefore falls below the fold exactly when width / height exceeds
   about 1.96. Anywhere squarer, the panel is already in view when the page
   loads and the button would be pointing at something the reader can see, so it
   is not rendered at all. The min-width keeps it away from phones held
   sideways, where the backdrop's floor — not 51vw — sets the height. */
.privacy-hero__jump {
  display: none;
}

@media (min-width: 900px) and (min-aspect-ratio: 196 / 100) {
  .privacy-hero__jump {
    display: inline-flex;
    /* The hero stretches its items, so the button has to opt out and shrink to
       its label. flex-start, not center: it is the continuation of the copy
       above it, so it shares the breadcrumb's and title's left edge rather than
       floating off the section's only alignment axis — and it then stays put
       relative to that copy as the frame widens. */
    align-self: flex-start;
    margin-top: clamp(1.75rem, 3.4vw, 3.25rem);
  }
}

.privacy-hero__jump-arrow {
  width: 1.1em;
  height: 1.1em;
  flex-shrink: 0;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform var(--transition);
}

/* .btn--outline already brightens the border and lights the glow on hover;
   the arrow adds the direction of travel. */
.privacy-hero__jump:hover .privacy-hero__jump-arrow,
.privacy-hero__jump:focus-visible .privacy-hero__jump-arrow {
  transform: translateY(0.2em);
}


/* --- 21.4 Policy panel ------------------------------------- */

.policy {
  padding: clamp(1.75rem, 3vw, 3rem) var(--pad-x);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

/* The panel is the jump button's target and carries tabindex="-1" so the jump
   moves focus, not just the scroll position. Keep the global focus ring but not
   the radius it would otherwise impose on a panel this size. */
.policy:focus-visible {
  border-radius: var(--radius-lg);
}

.policy__title {
  font-size: clamp(1.25rem, 0.95rem + 1.35vw, 2.5rem);
  font-weight: 700;
  line-height: 1.25;
  text-wrap: balance;
}

.policy__lead {
  max-width: 52rem;
  margin-top: clamp(0.75rem, 1.4vw, 1.25rem);
  font-size: clamp(0.95rem, 0.88rem + 0.5vw, 1.375rem);
  line-height: 1.7;
  color: var(--color-text-muted);
  text-wrap: pretty;
}


/* --- 21.5 Policy cards ------------------------------------- */

.policy-list {
  display: grid;
  gap: clamp(0.75rem, 1.4vw, 1.25rem);
  margin-top: clamp(1.75rem, 3.2vw, 2.75rem);
}

/* Each card is a button, not a link: it opens a dialog on this page rather
   than navigating anywhere. */
.policy-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: clamp(1rem, 2.2vw, 2rem);
  align-items: center;
  width: 100%;
  padding: clamp(1rem, 1.8vw, 1.75rem) clamp(1rem, 2vw, 2rem);
  text-align: left;
  background-color: var(--color-surface-soft);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background-color var(--transition), border-color var(--transition),
              box-shadow var(--transition);
}

.policy-card:hover,
.policy-card:focus-visible {
  background-color: var(--color-surface-raised);
  border-color: var(--color-border-bright);
  box-shadow: 0 0 28px rgba(59, 130, 246, 0.16);
}

/* The global focus ring rounds whatever it lands on to --radius-sm, which on a
   card this size would visibly reshape the corners. Restore the card's own. */
.policy-card:focus-visible {
  border-radius: var(--radius-md);
}

.policy-card__icon {
  display: grid;
  place-items: center;
  width: clamp(3rem, 5.4vw, 5.25rem);
  aspect-ratio: 1;
  /* A squircle, as in the reference — not a circle and not a plain rounded box. */
  border-radius: 30%;
  box-shadow: 0 8px 22px rgba(8, 10, 30, 0.5);
}

.policy-card__icon svg {
  width: 56%;
  height: 56%;
  fill: #ffffff;
  stroke: none;
}

.policy-card__icon--blue {
  background-image: linear-gradient(145deg, #3fa0ff 0%, #2d7ef2 100%);
}

.policy-card__icon--violet {
  background-image: linear-gradient(145deg, #9a6bff 0%, #7c3aed 100%);
}

.policy-card__text {
  display: flex;
  flex-direction: column;
  gap: 0.3em;
  min-width: 0;
}

.policy-card__title {
  font-size: clamp(1.05rem, 0.92rem + 0.7vw, 1.75rem);
  font-weight: 700;
  line-height: 1.25;
  color: var(--color-text);
}

.policy-card__sub {
  font-size: clamp(0.9rem, 0.85rem + 0.45vw, 1.25rem);
  line-height: 1.45;
  color: var(--color-text-muted);
  text-wrap: pretty;
}

.policy-card__chevron {
  width: clamp(1.4rem, 2.2vw, 2.25rem);
  height: clamp(1.4rem, 2.2vw, 2.25rem);
  flex-shrink: 0;
  fill: none;
  stroke: var(--color-text-bright);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform var(--transition), stroke var(--transition);
}

.policy-card:hover .policy-card__chevron,
.policy-card:focus-visible .policy-card__chevron {
  stroke: var(--color-text);
  transform: translateX(0.2em);
}


/* --- 21.6 Reassurance panel -------------------------------- */

.privacy-panel {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(1rem, 2.2vw, 2rem);
  align-items: center;
  margin-top: clamp(1.75rem, 3.2vw, 2.75rem);
  padding: clamp(1.25rem, 2.2vw, 2.25rem) clamp(1rem, 2vw, 2rem);
  background:
    linear-gradient(120deg, rgba(34, 211, 238, 0.13) 0%, rgba(34, 211, 238, 0.05) 60%, rgba(10, 16, 36, 0) 100%),
    var(--color-surface-soft);
  border: 1px solid rgba(45, 212, 191, 0.42);
  border-radius: var(--radius-md);
}

.privacy-panel__icon {
  display: grid;
  place-items: center;
  width: clamp(3.4rem, 6vw, 6rem);
  aspect-ratio: 1;
  border-radius: 30%;
  background-image: linear-gradient(145deg, #7ce8f0 0%, #2ec8d8 100%);
  box-shadow: 0 8px 24px rgba(8, 10, 30, 0.5);
}

.privacy-panel__icon svg {
  width: 56%;
  height: 56%;
  fill: #ffffff;
  stroke: none;
}

.privacy-panel__title {
  font-size: clamp(1.05rem, 0.92rem + 0.7vw, 1.75rem);
  font-weight: 600;
  line-height: 1.25;
  color: var(--color-cyan);
}

.privacy-panel__body p {
  margin-top: 0.45em;
  font-size: clamp(0.9rem, 0.85rem + 0.45vw, 1.25rem);
  line-height: 1.65;
  color: var(--color-text-muted);
  text-wrap: pretty;
}


/* --- 21.7 Full document and details ------------------------ */

.policy-download {
  margin-top: clamp(1.5rem, 2.8vw, 2.25rem);
}

/* The label is two parts — the action and the format — so the button has to
   wrap on a narrow phone. .btn suppresses wrapping for the pairs of short
   calls to action elsewhere; here it would overflow instead. */
.policy-download .btn {
  white-space: normal;
  text-align: left;
}

.policy-download__format {
  font-weight: 500;
  color: var(--color-text-muted);
}

.btn__download {
  width: 1.15em;
  height: 1.15em;
  flex-shrink: 0;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.policy-meta {
  margin-top: clamp(1rem, 2vw, 1.5rem);
  font-size: clamp(0.78rem, 0.75rem + 0.3vw, 1rem);
  line-height: 1.6;
  color: rgba(182, 194, 221, 0.72);
}


/* --- 21.8 Policy dialogs ----------------------------------- */

/* Shared by both legal pages: the privacy policy sections and the Terms of
   Service sections use these classes, so there is one dialog style, not two.
   The Terms dialogs add .terms-dialog alongside it purely as a scoping hook.

   The dialog element itself is the panel. `display` has to be re-declared
   under [open] only, or it would override the UA's `display: none` for the
   closed state and every dialog would sit in the page. */
.policy-dialog {
  max-width: min(58rem, calc(100vw - 2 * var(--frame-gutter) - 1rem));
  max-height: min(86vh, 60rem);
  padding: 0;
  color: var(--color-text);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border-bright);
  border-radius: var(--radius-lg);
  box-shadow: 0 30px 80px rgba(2, 6, 20, 0.7);
}

.policy-dialog[open] {
  display: flex;
  flex-direction: column;
}

.policy-dialog::backdrop {
  background-color: rgba(3, 5, 14, 0.72);
  backdrop-filter: blur(6px);
}

.policy-dialog__head {
  position: relative;
  flex: none;
  padding: clamp(1.25rem, 2.4vw, 2.25rem) clamp(1.25rem, 2.6vw, 2.5rem) clamp(1rem, 1.8vw, 1.5rem);
  /* The close control is absolutely placed in this gutter. */
  padding-right: clamp(3.75rem, 6vw, 5.5rem);
  background-color: var(--color-surface-soft);
  border-bottom: 1px solid var(--color-border);
}

.policy-dialog__eyebrow {
  font-size: clamp(0.72rem, 0.68rem + 0.22vw, 0.9rem);
  font-weight: 600;
  letter-spacing: 0.34em;
  text-indent: 0.34em;
  text-transform: uppercase;
  color: var(--color-cyan);
}

.policy-dialog__title {
  margin-top: 0.4em;
  font-size: clamp(1.35rem, 1.05rem + 1.2vw, 2.25rem);
  font-weight: 700;
  line-height: 1.2;
}

.policy-dialog__sub {
  margin-top: 0.25em;
  font-size: clamp(0.9rem, 0.85rem + 0.4vw, 1.125rem);
  color: var(--color-text-muted);
}

.policy-dialog__close {
  position: absolute;
  top: clamp(1rem, 2vw, 1.75rem);
  right: clamp(1rem, 2vw, 1.75rem);
  display: grid;
  place-items: center;
  width: clamp(2.25rem, 3.4vw, 3rem);
  height: clamp(2.25rem, 3.4vw, 3rem);
  background-color: rgba(10, 16, 36, 0.7);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: border-color var(--transition), background-color var(--transition);
}

.policy-dialog__close:hover {
  background-color: var(--color-surface-raised);
  border-color: var(--color-border-bright);
}

.policy-dialog__close:focus-visible {
  border-radius: var(--radius-pill);
}

/* The control stays visually 36px, as approved, but pointer targets extend to
   44px so the touch target clears WCAG 2.5.8 on phones. Purely a hit area: no
   paint, so neither legal page changes visually. */
.policy-dialog__close::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: max(100%, 44px);
  height: max(100%, 44px);
  transform: translate(-50%, -50%);
}

.policy-dialog__close svg {
  width: 52%;
  height: 52%;
  fill: none;
  stroke: var(--color-text-bright);
  stroke-width: 2;
  stroke-linecap: round;
}

.policy-dialog__body {
  flex: 1 1 auto;
  min-height: 0;
  padding: clamp(1.25rem, 2.4vw, 2.25rem) clamp(1.25rem, 2.6vw, 2.5rem) clamp(1.75rem, 3vw, 2.75rem);
  overflow-y: auto;
  overscroll-behavior: contain;
}


/* --- 21.9 Policy dialog content ---------------------------- */

.policy-dialog__body h3 {
  margin-top: clamp(1.5rem, 2.6vw, 2.25rem);
  font-size: clamp(1.05rem, 0.95rem + 0.55vw, 1.5rem);
  font-weight: 700;
  line-height: 1.3;
  color: var(--color-text);
}

.policy-dialog__body > h3:first-child {
  margin-top: 0;
}

.policy-dialog__body p,
.policy-dialog__body li {
  font-size: clamp(0.9rem, 0.86rem + 0.4vw, 1.1875rem);
  line-height: 1.75;
  color: var(--color-text-muted);
  text-wrap: pretty;
}

.policy-dialog__body p + p,
.policy-dialog__body h3 + p,
.policy-dialog__body ul + p {
  margin-top: 0.85em;
}

.policy-dialog__body strong {
  color: var(--color-text-bright);
}

.policy-dialog__body ul {
  display: grid;
  gap: 0.7em;
  margin-top: 0.85em;
  padding-left: 1.5em;
  list-style: disc;
}

.policy-dialog__body li::marker {
  color: var(--color-blue);
}

.policy-dialog__body a {
  color: var(--color-cyan);
  text-decoration: underline;
  text-underline-offset: 0.18em;
  overflow-wrap: anywhere;
}

.policy-dialog__body a:hover {
  color: var(--color-text);
}

.policy-dialog__body code {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.92em;
  color: var(--color-text-bright);
  overflow-wrap: anywhere;
}

/* Pulled-out notices that carry their own heading in the source document. */
.policy-callout {
  margin-top: clamp(1.1rem, 2vw, 1.6rem);
  padding: clamp(0.9rem, 1.6vw, 1.5rem) clamp(1rem, 1.8vw, 1.6rem);
  background-color: rgba(34, 211, 238, 0.07);
  border: 1px solid rgba(45, 212, 191, 0.34);
  border-radius: var(--radius-md);
}

.policy-callout h4 {
  font-size: clamp(0.95rem, 0.9rem + 0.45vw, 1.25rem);
  font-weight: 600;
  line-height: 1.35;
  color: var(--color-cyan);
}

.policy-callout p {
  margin-top: 0.5em;
}

/* Tables are wide by nature; the wrapper scrolls rather than forcing the
   dialog itself to. It is focusable so the scroll region is keyboard
   reachable, which is what role="region" promises. */
.policy-table-wrap {
  margin-top: clamp(1.1rem, 2vw, 1.6rem);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.policy-table {
  width: 100%;
  min-width: 34rem;
  border-collapse: collapse;
}

.policy-table th,
.policy-table td {
  padding: clamp(0.65rem, 1.2vw, 1.1rem) clamp(0.75rem, 1.4vw, 1.25rem);
  font-size: clamp(0.85rem, 0.82rem + 0.35vw, 1.0625rem);
  line-height: 1.65;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--color-border-soft);
}

.policy-table thead th {
  font-weight: 700;
  color: var(--color-text);
  background-color: var(--color-surface-soft);
}

.policy-table tbody th {
  width: 32%;
  font-weight: 600;
  color: var(--color-text-bright);
}

.policy-table tbody td {
  color: var(--color-text-muted);
}

.policy-table tbody tr:last-child th,
.policy-table tbody tr:last-child td {
  border-bottom: 0;
}

.policy-contact {
  display: grid;
  gap: 0.75rem;
  margin-top: clamp(1.1rem, 2vw, 1.6rem);
  padding: clamp(0.9rem, 1.6vw, 1.5rem) clamp(1rem, 1.8vw, 1.6rem);
  background-color: var(--color-surface-soft);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.policy-contact > div {
  display: grid;
  grid-template-columns: minmax(0, 11rem) minmax(0, 1fr);
  gap: 0.25rem 1rem;
}

.policy-contact dt {
  font-size: clamp(0.85rem, 0.82rem + 0.35vw, 1.0625rem);
  font-weight: 600;
  color: var(--color-text-bright);
}

.policy-contact dd {
  /* The UA indents <dd>; the grid already provides the alignment. */
  margin-inline-start: 0;
  font-size: clamp(0.85rem, 0.82rem + 0.35vw, 1.0625rem);
  line-height: 1.6;
  color: var(--color-text-muted);
  overflow-wrap: anywhere;
}

/* Locks the page behind an open dialog. main.js compensates for the removed
   scrollbar so nothing shifts sideways. */
.has-dialog {
  overflow: hidden;
}

/* Last resort for engines without <dialog>: main.js sets this class and the
   sections render in place, stacked after the frame, so the policy is still
   readable. The controls that only make sense in a modal are dropped. */
.no-dialog-support .policy-dialog,
.no-dialog-support .terms-dialog {
  display: flex;
  flex-direction: column;
  max-width: var(--container-width);
  max-height: none;
  margin: clamp(0.5rem, 1.2vw, 1rem) auto 0;
}

.no-dialog-support .policy-dialog__close,
.no-dialog-support .policy-card__chevron,
.no-dialog-support .terms-card__chevron {
  display: none;
}

.no-dialog-support .policy-card,
.no-dialog-support .terms-card {
  cursor: default;
}


/* --- 21.10 Privacy responsive behaviour -------------------- */

@media (max-width: 900px) {
  .policy-dialog {
    max-width: none;
    max-height: 92vh;
    /* dvh tracks the collapsing browser chrome; vh above is the fallback. */
    max-height: 92dvh;
    width: calc(100vw - 2 * var(--frame-gutter));
  }
}

@media (max-width: 620px) {
  /* The chevron is decoration on a control whose whole surface is the target;
     dropping it returns the width to the title and its description. */
  .policy-card {
    grid-template-columns: auto minmax(0, 1fr);
    gap: clamp(0.85rem, 3.4vw, 1.25rem);
  }

  .policy-card__chevron {
    display: none;
  }

  .privacy-panel {
    grid-template-columns: minmax(0, 1fr);
    justify-items: start;
    gap: clamp(0.85rem, 3.4vw, 1.25rem);
  }

  .policy-contact > div {
    grid-template-columns: minmax(0, 1fr);
  }

  .policy-table {
    min-width: 26rem;
  }
}


/* =========================================================
   22. PixelOrbit Studio Terms of Service
   ---------------------------------------------------------
   Scoped to .page-terms, or to class names used on that page
   alone, so the other three pages are untouched.

   22.1  Terms page shell
   22.2  Terms hero
   22.3  Hero flourish
   22.4  Terms panel and cards
   22.5  Card icons
   22.6  Brand callout
   22.7  Draft note
   22.8  Terms responsive behaviour
   ========================================================= */


/* --- 22.1 Terms page shell --------------------------------- */

/* The supplied artwork is 16:9 and object-fit: cover is width-constrained here,
   so the band's own aspect ratio decides how much of the picture survives. The
   reference band is a little under 1.7:1, which keeps the galaxy, the ridge line
   and the lake all in frame. 58vw holds that ratio as the frame widens; the cap
   matches the 2560px container. Below ~720px the floor takes over, because a
   band 58% of a phone's width is far too shallow to seat the hero copy. */
.page-terms {
  --sky-height: clamp(26rem, 58vw, 103rem);
}

.sky--terms {
  object-position: center 48%;
}

/* Darkens the left, where the breadcrumb, title and intro sit, and blends the
   artwork into the page before the Terms panel begins. The gradient is
   localised rather than a flat scrim, so the galaxy, ridges and reflection keep
   their colour. */
.sky__fade--terms {
  background:
    linear-gradient(
      to bottom,
      rgba(5, 7, 15, 0.58) 0%,
      rgba(5, 7, 15, 0.2) 22%,
      rgba(7, 11, 26, 0.14) 54%,
      rgba(7, 11, 26, 0.72) 86%,
      var(--color-bg) 100%
    ),
    linear-gradient(
      100deg,
      rgba(4, 6, 16, 0.88) 0%,
      rgba(4, 6, 16, 0.6) 34%,
      rgba(4, 6, 16, 0.12) 60%,
      rgba(4, 6, 16, 0) 74%
    );
}


/* --- 22.2 Terms hero --------------------------------------- */

/* Same construction as the privacy hero: --pad-x so the breadcrumb, headings
   and intro line up with the header's brand and the panel below, and a
   min-height so the band the reader sees keeps the ratio above instead of
   collapsing once the type hits its clamp ceilings. */
.terms-hero {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: calc(var(--sky-height) - var(--header-height) - var(--pad-frame));
  padding: clamp(1.25rem, 2.4vw, 2.5rem) var(--pad-x) clamp(2.5rem, 6vw, 6rem);
}

.terms-hero__title {
  /* Optical alignment: Outfit's left side bearing is about 0.057em, so at this
     size the ink would start ~5px inside the box while the breadcrumb and date
     start ~1px in. */
  margin-left: -0.045em;
  margin-top: clamp(1rem, 2.4vw, 2rem);
  font-size: clamp(2.5rem, 1rem + 6.2vw, 6rem);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.025em;
}

/* Second line of the same heading, so the pair reads as one title to assistive
   technology. Deliberately smaller than the H1 line above it. */
.terms-hero__brand {
  display: block;
  font-size: 0.85em;
  color: var(--color-pink);
}

.terms-hero__updated {
  margin-top: clamp(1.1rem, 2.4vw, 2rem);
  font-size: clamp(1rem, 0.9rem + 0.55vw, 1.5rem);
  color: var(--color-text-bright);
}

.terms-hero__lead {
  max-width: 46rem;
  margin-top: clamp(1rem, 2.2vw, 1.75rem);
  font-size: clamp(1rem, 0.92rem + 0.5vw, 1.375rem);
  line-height: 1.7;
  color: var(--color-text-bright);
  text-wrap: pretty;
}

/* Jump to the Terms.
   Hidden by default and revealed only where it earns its place. This backdrop is
   58vw tall — deeper than the 51vw behind the privacy hero — so the Terms panel
   starts roughly 0.58 * viewport-width down the page and falls below the fold
   once width / height passes about 1.71. That is why the threshold here is not
   the one the privacy page uses: the number follows this hero's geometry rather
   than being copied across. Anywhere squarer, the panel is already in view when
   the page loads and the button would point at something the reader can see, so
   it is not rendered at all. The min-width keeps it away from phones held
   sideways, where the backdrop's floor — not 58vw — sets the height. */
.terms-hero__jump {
  display: none;
}

@media (min-width: 900px) and (min-aspect-ratio: 171 / 100) {
  .terms-hero__jump {
    display: inline-flex;
    /* The hero stretches its items, so the button has to opt out and shrink to
       its label. flex-start, not center: it is the continuation of the copy
       above it, so it shares the breadcrumb's and title's left edge. */
    align-self: flex-start;
    margin-top: clamp(1.75rem, 3.4vw, 3.25rem);
  }
}

/* The label is longer than the paired calls to action elsewhere, and .btn
   suppresses wrapping for those; here that would overflow instead. */
.terms-hero__jump.btn {
  white-space: normal;
  text-align: left;
}

.terms-hero__jump-arrow {
  width: 1.1em;
  height: 1.1em;
  flex-shrink: 0;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform var(--transition);
}

/* .btn--outline already brightens the border and lights the glow on hover;
   the arrow adds the direction of travel. */
.terms-hero__jump:hover .terms-hero__jump-arrow,
.terms-hero__jump:focus-visible .terms-hero__jump-arrow {
  transform: translateY(0.2em);
}


/* --- 22.3 Hero flourish ------------------------------------ */

/* Decoration only. Absolutely placed against the hero's right edge so it never
   takes part in the copy's layout and can never push it around. */
.terms-flourish {
  --flourish-w: clamp(7rem, 11vw, 13rem);
  position: absolute;
  top: 18%;
  right: var(--pad-x);
  display: flex;
  flex-direction: column;
  align-items: center;
  width: var(--flourish-w);
  pointer-events: none;
}

.terms-script {
  /* Sized from the column it must fit inside rather than from the viewport:
     a viewport ramp lets the longest word outgrow the column and overflow it. */
  max-width: 100%;
  font-family: "Caveat", "Segoe Script", "Bradley Hand", cursive;
  font-size: clamp(1.1rem, calc(var(--flourish-w) / 4.6), 3rem);
  font-weight: 600;
  line-height: 1.1;
  text-align: center;
  color: #eaf0ff;
  text-shadow: 0 0 18px rgba(150, 170, 255, 0.55);
  transform: rotate(-7deg);
}

/* Width and height are stated outright alongside the viewBox: with `height:
   auto` the height is derived from a width a column flex container may not have
   resolved yet, and the element can collapse to nothing. */
.terms-comet {
  flex: none;
  /* Taller than it is wide, matching the supplied decoration: sparkle up at the
     top right, tail curving down to the dot at the lower left. */
  width: calc(var(--flourish-w) * 0.55);
  height: auto;
  aspect-ratio: 120 / 200;
  margin-top: 0.4rem;
  overflow: visible;
}

.terms-comet__trail {
  fill: none;
  stroke: #f2f6ff;
  stroke-width: 2.2;
  stroke-linecap: round;
  opacity: 0.85;
  vector-effect: non-scaling-stroke;
}

.terms-comet__star {
  fill: #ffd04a;
  stroke: none;
  filter: drop-shadow(0 0 9px rgba(255, 199, 90, 0.85));
}

/* The tail terminates in a bright dot rather than tapering away. */
.terms-comet__dot {
  fill: #f6f9ff;
  stroke: none;
  filter: drop-shadow(0 0 7px rgba(214, 228, 255, 0.85));
}


/* --- 22.4 Terms panel and cards ---------------------------- */

.terms {
  padding: clamp(1.75rem, 3vw, 3rem) var(--pad-x);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

/* The panel is the jump button's target and carries tabindex="-1" so the jump
   moves focus, not just the scroll position. Keep the global focus ring but not
   the radius it would otherwise impose on a panel this size. */
.terms:focus-visible {
  border-radius: var(--radius-lg);
}

.terms-list {
  display: grid;
  gap: clamp(0.65rem, 1.2vw, 1.1rem);
}

/* Each card is a button, not a link: it opens a dialog on this page rather than
   navigating anywhere. Metrics below are unchanged from the approved layout —
   only the properties a <button> needs have been added. */
.terms-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: clamp(0.9rem, 2vw, 1.75rem);
  align-items: center;
  width: 100%;
  padding: clamp(0.9rem, 1.6vw, 1.5rem) clamp(1rem, 2vw, 2rem);
  text-align: left;
  background-color: var(--color-surface-soft);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background-color var(--transition), border-color var(--transition),
              box-shadow var(--transition);
}

.terms-card:hover,
.terms-card:focus-visible {
  background-color: var(--color-surface-raised);
  border-color: var(--color-border-bright);
  box-shadow: 0 0 26px rgba(59, 130, 246, 0.15);
}

/* The global focus ring rounds whatever it lands on to --radius-sm, which on a
   card this size would visibly reshape the corners. Restore the card's own. */
.terms-card:focus-visible {
  border-radius: var(--radius-md);
}

.terms-card__text {
  display: flex;
  flex-direction: column;
  gap: 0.28em;
  min-width: 0;
}

.terms-card__title {
  font-size: clamp(1rem, 0.9rem + 0.66vw, 1.625rem);
  font-weight: 700;
  line-height: 1.25;
  color: var(--color-text);
}

.terms-card__sub {
  font-size: clamp(0.875rem, 0.83rem + 0.42vw, 1.1875rem);
  line-height: 1.45;
  color: var(--color-text-muted);
  text-wrap: pretty;
}

.terms-card__chevron {
  width: clamp(1.3rem, 2vw, 2rem);
  height: clamp(1.3rem, 2vw, 2rem);
  flex-shrink: 0;
  fill: none;
  stroke: var(--color-text-bright);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform var(--transition), stroke var(--transition);
}

.terms-card:hover .terms-card__chevron {
  stroke: var(--color-text);
  transform: translateX(0.18em);
}


/* --- 22.5 Card icons --------------------------------------- */

.terms-card__icon {
  display: grid;
  place-items: center;
  width: clamp(2.9rem, 5.6vw, 5.5rem);
  aspect-ratio: 1;
  /* A squircle, as in the reference — not a circle and not a plain rounded box. */
  border-radius: 30%;
  box-shadow: 0 8px 22px rgba(8, 10, 30, 0.5);
}

.terms-card__icon svg {
  width: 56%;
  height: 56%;
  fill: #ffffff;
  stroke: none;
}

/* The reference cycles violet, cyan, pink down the nine cards. */
.terms-card__icon--violet {
  background-image: linear-gradient(145deg, #8b6bff 0%, #6d28f0 100%);
}

.terms-card__icon--cyan {
  background-image: linear-gradient(145deg, #45c8fb 0%, #1f8fe8 100%);
}

.terms-card__icon--pink {
  background-image: linear-gradient(145deg, #f48ae8 0%, #d84fc4 100%);
}


/* --- 22.6 Brand callout ------------------------------------ */

.terms-callout {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(1rem, 2.2vw, 2rem);
  align-items: center;
  margin-top: clamp(1.5rem, 2.8vw, 2.5rem);
  padding: clamp(1.25rem, 2.2vw, 2.25rem) clamp(1rem, 2vw, 2rem);
  background:
    linear-gradient(120deg, rgba(34, 211, 238, 0.13) 0%, rgba(34, 211, 238, 0.05) 60%, rgba(10, 16, 36, 0) 100%),
    var(--color-surface-soft);
  border: 1px solid rgba(45, 212, 191, 0.42);
  border-radius: var(--radius-md);
}

.terms-callout__icon {
  display: grid;
  place-items: center;
  width: clamp(3.4rem, 6vw, 6rem);
  aspect-ratio: 1;
  border-radius: 30%;
  background-image: linear-gradient(145deg, #7ce8f0 0%, #2ec8d8 100%);
  box-shadow: 0 8px 24px rgba(8, 10, 30, 0.5);
}

.terms-callout__icon svg {
  width: 56%;
  height: 56%;
  fill: #ffffff;
  stroke: none;
}

.terms-callout__title {
  font-size: clamp(1.05rem, 0.92rem + 0.7vw, 1.75rem);
  font-weight: 600;
  line-height: 1.25;
  color: var(--color-cyan);
}

.terms-callout__body p {
  margin-top: 0.45em;
  font-size: clamp(0.9rem, 0.85rem + 0.45vw, 1.25rem);
  line-height: 1.65;
  color: var(--color-text-muted);
  text-wrap: pretty;
}


/* --- 22.7 Terms responsive behaviour ----------------------- */

/* The flourish sits in the hero's right margin. Below this the copy needs that
   width, so it is dropped rather than shrunk into the text. */
@media (max-width: 1024px) {
  .terms-flourish {
    display: none;
  }
}

@media (max-width: 620px) {
  /* The chevron is decoration on a non-interactive card; dropping it returns
     the width to the title and its description. */
  .terms-card {
    grid-template-columns: auto minmax(0, 1fr);
    gap: clamp(0.8rem, 3.2vw, 1.15rem);
  }

  .terms-card__chevron {
    display: none;
  }

  .terms-callout {
    grid-template-columns: minmax(0, 1fr);
    justify-items: start;
    gap: clamp(0.85rem, 3.4vw, 1.25rem);
  }
}


/* =========================================================
   23. PixelOrbit Studio About Page
   ---------------------------------------------------------
   Scoped to .page-about, or to class names used on that page
   alone. The header, footer, buttons, breadcrumb and the
   whole value-icon system are reused as-is — nothing shared
   is redeclared here.

   23.1  About page base
   23.2  About hero
   23.3  Decorative script lettering
   23.4  Section pill and accent heading
   23.5  Our Story
   23.6  Our Values
   23.7  Our Mission
   23.8  About CTA
   23.9  About responsive behaviour
   ========================================================= */


/* --- 23.1 About page base ---------------------------------- */

/* The artwork is 16:9 and object-fit: cover is width-constrained here, so the
   band's aspect ratio decides how much of the picture survives. The reference
   band is a little under 1.9:1, which keeps the nebula, the ridge line and the
   lake in frame while leaving the left third dark enough for the copy. 52vw
   holds that ratio as the frame widens; the cap matches the 2560px container,
   and below ~740px the floor takes over because a band 52% of a phone's width
   would be far too shallow to seat the hero copy. */
.page-about {
  --sky-height: clamp(24rem, 52vw, 92rem);
}

.sky--about {
  object-position: center 46%;
}

/* Darkens the left, where the breadcrumb, headings and body sit, and blends the
   artwork into the page before the Our Story panel begins. Localised rather
   than a flat scrim, so the nebula, mountains and lake keep their colour. */
.sky__fade--about {
  background:
    linear-gradient(
      to bottom,
      rgba(5, 7, 15, 0.55) 0%,
      rgba(5, 7, 15, 0.18) 22%,
      rgba(7, 11, 26, 0.12) 56%,
      rgba(7, 11, 26, 0.7) 87%,
      var(--color-bg) 100%
    ),
    linear-gradient(
      100deg,
      rgba(4, 6, 16, 0.9) 0%,
      rgba(4, 6, 16, 0.62) 32%,
      rgba(4, 6, 16, 0.14) 58%,
      rgba(4, 6, 16, 0) 72%
    );
}


/* --- 23.2 About hero --------------------------------------- */

/* Same construction as the Terms and privacy heroes: --pad-x so the breadcrumb,
   headings and body line up with the header's brand and the panels below, and a
   min-height so the band the reader sees holds the ratio above instead of
   collapsing once the type hits its clamp ceilings. */
.about-hero {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: calc(var(--sky-height) - var(--header-height) - var(--pad-frame));
  padding: clamp(1.25rem, 2.4vw, 2.5rem) var(--pad-x) clamp(2.5rem, 6vw, 6rem);
}

.about-hero__title {
  /* Optical alignment: Outfit's left side bearing is about 0.057em, so at this
     size the ink would start ~5px inside the box while the breadcrumb and
     tagline start ~1px in. */
  margin-left: -0.045em;
  margin-top: clamp(1rem, 2.4vw, 2rem);
  font-size: clamp(2.5rem, 1rem + 6.2vw, 6rem);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.025em;
}

/* Second line of the same heading, so the pair reads as one title to assistive
   technology. Deliberately smaller than the line above it. */
.about-hero__brand {
  display: block;
  font-size: 0.85em;
  color: var(--color-pink);
}

.about-hero__tagline {
  margin-top: clamp(1rem, 2.2vw, 1.75rem);
  font-size: clamp(1.05rem, 0.95rem + 0.62vw, 1.625rem);
  font-weight: 600;
  color: var(--color-text);
}

.about-hero__lead {
  max-width: 34rem;
  margin-top: clamp(0.9rem, 1.8vw, 1.5rem);
  font-size: clamp(0.95rem, 0.9rem + 0.5vw, 1.3125rem);
  line-height: 1.75;
  color: var(--color-text-bright);
  text-wrap: pretty;
}

/* Jump to Our Story.
   Hidden by default and revealed only where it earns its place. This backdrop is
   52vw tall, and the Our Story heading sits a further ~180px inside the panel
   behind its padding and pill, so measured across real sizes the heading drops
   below the fold once width / height reaches about 1.6. The
   threshold is derived from this hero's own geometry, not copied from the other
   pages, whose backdrops are different depths. Anywhere squarer, the panel is
   already in view when the page loads and the button would point at something
   the reader can see, so it is not rendered at all. The min-width keeps it away
   from phones held sideways, where the backdrop's floor — not 52vw — sets the
   height. */
.about-hero__jump {
  display: none;
}

@media (min-width: 900px) and (min-aspect-ratio: 8 / 5) {
  .about-hero__jump {
    display: inline-flex;
    /* The hero stretches its items, so the button has to opt out and shrink to
       its label. flex-start, not center: it is the continuation of the copy
       above it, so it shares the breadcrumb's and title's left edge. */
    align-self: flex-start;
    margin-top: clamp(1.75rem, 3.4vw, 3.25rem);
  }
}

/* The label is longer than the paired calls to action elsewhere, and .btn
   suppresses wrapping for those; here that would overflow instead. */
.about-hero__jump.btn {
  white-space: normal;
  text-align: left;
}

.about-hero__jump-arrow {
  width: 1.1em;
  height: 1.1em;
  flex-shrink: 0;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform var(--transition);
}

/* .btn--outline already brightens the border and lights the glow on hover;
   the arrow adds the direction of travel. */
.about-hero__jump:hover .about-hero__jump-arrow,
.about-hero__jump:focus-visible .about-hero__jump-arrow {
  transform: translateY(0.2em);
}


/* --- 23.3 Decorative script lettering ---------------------- */

/* Decoration only. Absolutely placed against the hero's right edge so it never
   takes part in the copy's layout and can never push it around. */
.about-flourish {
  --flourish-w: clamp(7rem, 11vw, 13rem);
  position: absolute;
  top: 20%;
  right: var(--pad-x);
  display: flex;
  flex-direction: column;
  align-items: center;
  width: var(--flourish-w);
  pointer-events: none;
}

.about-script {
  /* Sized from the column it must fit inside rather than from the viewport: a
     viewport ramp lets the longest word outgrow the column and overflow it. */
  max-width: 100%;
  font-family: "Caveat", "Segoe Print", "Bradley Hand", cursive;
  font-weight: 600;
  line-height: 1.1;
  text-align: center;
  color: #eaf0ff;
  text-shadow: 0 0 18px rgba(150, 170, 255, 0.55);
}

.about-flourish .about-script {
  font-size: clamp(1.1rem, calc(var(--flourish-w) / 4.6), 3rem);
  transform: rotate(-7deg);
}

/* Width and height are stated outright alongside the viewBox: with `height:
   auto` the height is derived from a width a column flex container may not have
   resolved yet, and the element can collapse to nothing. */
.about-comet {
  flex: none;
  /* Taller than it is wide, matching the supplied decoration: sparkle up at the
     top right, tail curving down to the dot at the lower left. */
  width: calc(var(--flourish-w) * 0.55);
  height: auto;
  aspect-ratio: 120 / 200;
  margin-top: 0.4rem;
  overflow: visible;
}

.about-comet__trail {
  fill: none;
  stroke: #f2f6ff;
  stroke-width: 2.2;
  stroke-linecap: round;
  opacity: 0.85;
  vector-effect: non-scaling-stroke;
}

.about-comet__star {
  fill: #ffd04a;
  stroke: none;
  filter: drop-shadow(0 0 9px rgba(255, 199, 90, 0.85));
}

/* The tail terminates in a bright dot rather than tapering away. */
.about-comet__dot {
  fill: #f6f9ff;
  stroke: none;
  filter: drop-shadow(0 0 7px rgba(214, 228, 255, 0.85));
}

.about-swoosh {
  display: block;
  width: 100%;
  height: auto;
  margin-top: 0.3rem;
  overflow: visible;
}

.about-swoosh path {
  fill: none;
  stroke-width: 2.4;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

.about-swoosh--violet path {
  stroke: var(--color-purple);
  filter: drop-shadow(0 0 6px rgba(168, 85, 247, 0.6));
}

.about-swoosh--blue path {
  stroke: var(--color-blue);
  filter: drop-shadow(0 0 6px rgba(56, 189, 248, 0.6));
}


/* --- 23.4 Section pill and accent heading ------------------ */

/* The reference's small label: violet edge on the left, cyan on the right. The
   gradient border is painted with a mask so the interior stays translucent. */
.pill {
  align-self: flex-start;
  display: inline-block;
  position: relative;
  padding: 0.5em 1.25em;
  font-size: clamp(0.8125rem, 0.78rem + 0.3vw, 1.0625rem);
  font-weight: 500;
  color: var(--color-text);
  background: rgba(8, 14, 30, 0.55);
  border-radius: var(--radius-pill);
  backdrop-filter: blur(4px);
}

.pill::before {
  content: "";
  position: absolute;
  inset: 0;
  padding: 1px;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--color-violet) 0%, rgba(120, 130, 220, 0.5) 50%, var(--color-cyan) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  pointer-events: none;
}

.accent-gradient {
  color: var(--color-pink);
}

@supports ((background-clip: text) or (-webkit-background-clip: text)) {
  .accent-gradient {
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    background-image: var(--gradient-nebula);
  }
}


/* --- 23.5 Our Story ---------------------------------------- */

/* The panel is the jump button's target and carries tabindex="-1" so the jump
   moves focus, not just the scroll position. The global focus ring applies; only
   the radius it would otherwise impose on a panel this size is overridden. */
.story:focus-visible {
  border-radius: var(--radius-lg);
}

.story {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 3vw, 3rem);
  align-items: center;
  min-height: clamp(20rem, 34vw, 44rem);
  padding: clamp(1.75rem, 3.2vw, 3.25rem) var(--pad-x);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.story__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Keeps the Earth horizon low and the nebula upper-right, as in the reference. */
  object-position: center 38%;
}

/* Darkens the left for the copy without flattening the Earth glow on the right. */
.story__fade {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    linear-gradient(
      100deg,
      rgba(5, 8, 20, 0.92) 0%,
      rgba(5, 8, 20, 0.7) 34%,
      rgba(5, 8, 20, 0.2) 58%,
      rgba(5, 8, 20, 0) 74%
    );
}

.story__copy {
  /* Placed explicitly rather than by auto-flow. The backdrop and its fade are
     absolutely positioned children of this grid, and leaving the two real
     columns to auto-placement let one of them take a cell and push the copy
     into the right-hand column. */
  grid-column: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.story__title {
  margin-top: clamp(0.9rem, 1.8vw, 1.5rem);
  font-size: clamp(1.6rem, 1rem + 2.5vw, 3.5rem);
  font-weight: 700;
  line-height: 1.16;
  letter-spacing: -0.02em;
}

.story__text {
  max-width: 34rem;
  margin-top: clamp(0.9rem, 1.8vw, 1.5rem);
  font-size: clamp(0.9rem, 0.86rem + 0.42vw, 1.25rem);
  line-height: 1.7;
  color: var(--color-text-bright);
  text-wrap: pretty;
}

.story__visual {
  grid-column: 2;
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* The official shared logo asset, scaled by CSS only — the artwork itself is
   untouched. The wrapper sizes it and supplies the ground beneath it. */
.story__logo-wrap {
  position: relative;
  display: block;
  /* The reference sizes the mark at roughly 18% of the frame; the cap only has
     to stop it growing past the 2560px container. */
  width: clamp(8rem, 18vw, 36rem);
}

/* The mark's centre panel is transparent, so over the nebula the white star
   inside it had nothing to read against. This pool restores the dark ground the
   panel sits on everywhere else on the site. It is wider than the mark and
   fades to nothing well inside its own edge, so it reads as depth in space
   rather than a disc pasted behind the logo, and the Earth glow, stars and
   nebula around it stay visible. */
.story__logo-wrap::before {
  content: "";
  position: absolute;
  inset: -16%;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(
    circle at 50% 47%,
    rgba(4, 7, 18, 0.94) 0%,
    rgba(4, 7, 18, 0.88) 30%,
    rgba(4, 7, 18, 0.62) 50%,
    rgba(4, 7, 18, 0.24) 66%,
    rgba(4, 7, 18, 0) 80%
  );
}

.story__logo {
  position: relative;
  display: block;
  width: 100%;
  height: auto;
  filter: drop-shadow(0 0 34px rgba(99, 102, 241, 0.45));
}

.story__decor {
  width: clamp(6.5rem, 11vw, 13rem);
  margin-top: clamp(0.5rem, 1.4vw, 1.25rem);
  align-self: flex-end;
  pointer-events: none;
}

.about-script--story {
  font-size: clamp(1.05rem, 2vw, 2.4rem);
  transform: rotate(-6deg);
}


/* --- 23.6 Our Values --------------------------------------- */

.about-values {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  margin-top: clamp(1rem, 2vw, 1.5rem);
  padding: clamp(1.75rem, 3.2vw, 3.25rem) var(--pad-x);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.about-values__title {
  margin-top: clamp(0.9rem, 1.8vw, 1.5rem);
  font-size: clamp(1.6rem, 1rem + 2.5vw, 3.5rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.about-values__lead {
  max-width: 40rem;
  margin-top: clamp(0.5rem, 1vw, 0.9rem);
  font-size: clamp(0.9rem, 0.86rem + 0.42vw, 1.25rem);
  line-height: 1.6;
  color: var(--color-text-muted);
  text-wrap: pretty;
}

.about-values__grid {
  width: 100%;
  margin-top: clamp(1.5rem, 2.8vw, 2.5rem);
}

/* The reference gives each value its own card. Everything inside — icon, ring,
   accent, title, text, hover — is the homepage value system, unchanged. */
.about-vcard {
  justify-content: flex-start;
  padding: clamp(1.1rem, 2vw, 1.85rem) clamp(0.85rem, 1.6vw, 1.5rem);
  background-color: var(--color-surface-soft);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition: border-color var(--transition), box-shadow var(--transition);
}

.about-vcard:hover {
  border-color: var(--color-border-bright);
  box-shadow: 0 0 26px rgba(59, 130, 246, 0.14);
}


/* --- 23.7 Our Mission -------------------------------------- */

.mission {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 3vw, 3rem);
  align-items: center;
  margin-top: clamp(1rem, 2vw, 1.5rem);
  padding: clamp(1.75rem, 3.2vw, 3.25rem) var(--pad-x);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.mission__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.mission__title {
  margin-top: clamp(0.9rem, 1.8vw, 1.5rem);
  font-size: clamp(1.6rem, 1rem + 2.5vw, 3.5rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.mission__text {
  max-width: 36rem;
  margin-top: clamp(0.9rem, 1.8vw, 1.5rem);
  font-size: clamp(0.9rem, 0.86rem + 0.42vw, 1.25rem);
  line-height: 1.7;
  color: var(--color-text-bright);
  text-wrap: pretty;
}

.mission__card {
  position: relative;
  overflow: hidden;
  margin: 0;
  border: 1px solid var(--color-border-bright);
  border-radius: var(--radius-md);
}

.mission__img {
  display: block;
  width: 100%;
  /* The supplied artwork is 16:9 and the reference card is close to it, so the
     crop is slight and the composition survives intact. */
  aspect-ratio: 16 / 9;
  height: auto;
  object-fit: cover;
  object-position: center;
}

.mission__decor {
  position: absolute;
  right: 5%;
  bottom: 12%;
  width: clamp(7rem, 15vw, 15rem);
  pointer-events: none;
}

.about-script--mission {
  font-size: clamp(0.95rem, 1.9vw, 2.2rem);
  transform: rotate(-5deg);
  text-shadow: 0 0 14px rgba(10, 14, 34, 0.9), 0 0 24px rgba(150, 170, 255, 0.45);
}


/* --- 23.8 About CTA ---------------------------------------- */

.about-cta {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: clamp(1rem, 2.2vw, 2rem);
  align-items: center;
  margin-top: clamp(1rem, 2vw, 1.5rem);
  padding: clamp(1.25rem, 2.2vw, 2.25rem) clamp(1.25rem, 2.4vw, 2.5rem);
  background:
    linear-gradient(120deg, rgba(34, 211, 238, 0.1) 0%, rgba(34, 211, 238, 0.04) 60%, rgba(10, 16, 36, 0) 100%),
    var(--color-surface);
  border: 1px solid rgba(56, 189, 248, 0.4);
  border-radius: var(--radius-lg);
}

.about-cta__icon {
  display: grid;
  place-items: center;
  width: clamp(3.4rem, 6vw, 6rem);
  aspect-ratio: 1;
  border-radius: 30%;
  background-image: linear-gradient(145deg, #8b6bff 0%, #6d28f0 100%);
  box-shadow: 0 8px 24px rgba(8, 10, 30, 0.5);
}

.about-cta__icon svg {
  width: 56%;
  height: 56%;
  fill: #ffffff;
  stroke: none;
}

.about-cta__title {
  font-size: clamp(1.05rem, 0.92rem + 0.75vw, 1.875rem);
  font-weight: 700;
  line-height: 1.25;
}

.about-cta__text {
  margin-top: 0.4em;
  font-size: clamp(0.9rem, 0.85rem + 0.45vw, 1.1875rem);
  line-height: 1.55;
  color: var(--color-text-muted);
  text-wrap: pretty;
}

.about-cta__btn {
  flex-shrink: 0;
}


/* --- 23.9 About responsive behaviour ----------------------- */

/* The hero flourish sits in the hero's right margin. Below this the copy needs
   that width, so it is dropped rather than shrunk into the text. */
@media (max-width: 1024px) {
  .about-flourish {
    display: none;
  }
}

@media (max-width: 900px) {
  /* Story and mission stack: copy first, visual after, as in the reference's
     mobile reading order. */
  .story,
  .mission {
    grid-template-columns: minmax(0, 1fr);
  }

  .story {
    min-height: 0;
  }

  .story__copy,
  .story__visual {
    grid-column: 1;
  }

  .story__visual {
    margin-top: clamp(1.25rem, 4vw, 2rem);
  }

  .story__decor {
    align-self: center;
  }

  .about-cta {
    grid-template-columns: auto minmax(0, 1fr);
    row-gap: clamp(1rem, 3vw, 1.5rem);
  }

  /* The button drops to its own full-width row beneath the icon and copy. */
  .about-cta__btn {
    grid-column: 1 / -1;
    justify-self: start;
  }
}

@media (max-width: 620px) {
  .about-cta {
    grid-template-columns: minmax(0, 1fr);
    justify-items: start;
  }

  .about-cta__btn {
    grid-column: auto;
  }

  /* At this width the phrase would sit on the busiest part of the artwork. */
  .mission__decor {
    right: 4%;
    bottom: 8%;
    width: min(52%, 9rem);
  }
}


/* =========================================================
   24. PixelOrbit Studio Contact Page
   ---------------------------------------------------------
   Scoped to .page-contact, or to class names used on that
   page alone. The header, footer, buttons, breadcrumb, pill,
   accent heading and the value-icon system are reused as-is.

   24.1  Contact page base
   24.2  Contact hero
   24.3  Panels and layout
   24.4  Form fields
   24.5  Attachment drop zone
   24.6  Validation and status
   24.7  Contact information
   24.8  Location map
   24.9  Why contact us
   24.10 FAQ
   24.11 Contact responsive behaviour
   ========================================================= */


/* --- 24.1 Contact page base -------------------------------- */

/* The artwork is 16:9 and object-fit: cover is width-constrained here, so the
   band's aspect ratio decides how much of the picture survives. The reference
   band is a little over 2:1, which keeps the nebula, ridge line and forest in
   frame while leaving the left third dark enough for the copy. 48vw holds that
   ratio as the frame widens; the cap matches the 2560px container, and below
   ~800px the floor takes over. */
.page-contact {
  --sky-height: clamp(24rem, 48vw, 85rem);
}

.sky--contact {
  object-position: center 44%;
}

.sky__fade--contact {
  background:
    linear-gradient(
      to bottom,
      rgba(5, 7, 15, 0.55) 0%,
      rgba(5, 7, 15, 0.18) 22%,
      rgba(7, 11, 26, 0.12) 56%,
      rgba(7, 11, 26, 0.72) 88%,
      var(--color-bg) 100%
    ),
    linear-gradient(
      100deg,
      rgba(4, 6, 16, 0.92) 0%,
      rgba(4, 6, 16, 0.66) 34%,
      rgba(4, 6, 16, 0.16) 60%,
      rgba(4, 6, 16, 0) 74%
    );
}


/* --- 24.2 Contact hero ------------------------------------- */

.contact-hero {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: calc(var(--sky-height) - var(--header-height) - var(--pad-frame));
  padding: clamp(1.25rem, 2.4vw, 2.5rem) var(--pad-x) clamp(2.5rem, 5vw, 5rem);
}

.contact-hero__title {
  /* Optical alignment: Outfit's left side bearing is about 0.057em, so at this
     size the ink would start ~5px inside the box while the breadcrumb and
     tagline start ~1px in. */
  margin-left: -0.045em;
  margin-top: clamp(1rem, 2.4vw, 2rem);
  font-size: clamp(2.25rem, 1rem + 5.4vw, 5.25rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.025em;
}

/* Inline within the same heading line. The colour is the genuine fallback
   wherever background-clip: text is unavailable. */
.contact-hero__brand {
  color: var(--color-pink);
}

.contact-hero__tagline {
  margin-top: clamp(0.9rem, 2vw, 1.6rem);
  font-size: clamp(1rem, 0.92rem + 0.6vw, 1.5625rem);
  font-weight: 600;
  color: var(--color-text);
}

.contact-hero__lead {
  max-width: 34rem;
  margin-top: clamp(0.75rem, 1.6vw, 1.35rem);
  font-size: clamp(0.9rem, 0.86rem + 0.45vw, 1.25rem);
  line-height: 1.75;
  color: var(--color-text-bright);
  text-wrap: pretty;
}

/* Reuses the About page's script + comet decoration wholesale; only the
   placement differs. */
.contact-flourish {
  --flourish-w: clamp(7rem, 11vw, 13rem);
  position: absolute;
  top: 16%;
  right: var(--pad-x);
  display: flex;
  flex-direction: column;
  align-items: center;
  width: var(--flourish-w);
  pointer-events: none;
}

.contact-script {
  font-size: clamp(1rem, calc(var(--flourish-w) / 5.4), 2.6rem);
  transform: rotate(-8deg);
}


/* --- 24.3 Panels and layout -------------------------------- */

.contact-main {
  display: grid;
  grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
  gap: clamp(0.75rem, 1.4vw, 1.25rem);
  align-items: start;
}

.contact-aside {
  display: grid;
  gap: clamp(0.75rem, 1.4vw, 1.25rem);
}

.contact-panel {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: clamp(1.4rem, 2.6vw, 2.5rem) clamp(1.25rem, 2.2vw, 2.25rem);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.contact-panel__title {
  margin-top: clamp(0.75rem, 1.4vw, 1.25rem);
  font-size: clamp(1.4rem, 1rem + 1.7vw, 2.75rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

/* Panels without a pill above them start at the top of their own box. */
.contact-panel__title--plain {
  margin-top: 0;
}

.contact-panel__lead {
  max-width: 34rem;
  margin-top: clamp(0.5rem, 1vw, 0.9rem);
  font-size: clamp(0.875rem, 0.84rem + 0.4vw, 1.1875rem);
  line-height: 1.65;
  color: var(--color-text-muted);
  text-wrap: pretty;
}


/* --- 24.4 Form fields -------------------------------------- */

.cform {
  --field-h: clamp(3rem, 4.2vw, 3.5rem);
  width: 100%;
  margin-top: clamp(1.1rem, 2.2vw, 1.85rem);
}

.cform__row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(0.75rem, 1.4vw, 1.25rem);
}

.cform__field {
  display: flex;
  flex-direction: column;
  min-width: 0;
  margin-bottom: clamp(0.9rem, 1.6vw, 1.35rem);
}

.cform__label {
  display: flex;
  gap: 0.4em;
  align-items: center;
  margin-bottom: 0.5em;
  font-size: clamp(0.85rem, 0.82rem + 0.35vw, 1.0625rem);
  font-weight: 500;
  color: var(--color-text-bright);
}

.cform__label-icon {
  width: 1.05em;
  height: 1.05em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linejoin: round;
}

/* The asterisk is decorative; `required` carries the meaning, and each label
   also spells out "(optional)" where a field is not required, so requiredness
   is never signalled by colour alone. */
.cform__req {
  color: var(--color-pink);
}

.cform__optional {
  font-weight: 400;
  color: var(--color-text-muted);
}

.cform__control {
  position: relative;
  display: flex;
  align-items: center;
}

.cform__icon {
  position: absolute;
  left: clamp(0.75rem, 1.2vw, 1rem);
  width: 1.15em;
  height: 1.15em;
  fill: none;
  stroke: var(--color-text-muted);
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
  pointer-events: none;
}

.cform__icon--area {
  top: clamp(0.85rem, 1.4vw, 1.1rem);
}

.cform__input {
  width: 100%;
  min-height: var(--field-h);
  padding: 0.75em clamp(0.85rem, 1.4vw, 1.1rem);
  padding-left: clamp(2.6rem, 3.6vw, 3.1rem);
  font: inherit;
  font-size: clamp(0.9rem, 0.86rem + 0.4vw, 1.125rem);
  color: var(--color-text);
  background-color: rgba(8, 14, 32, 0.78);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition: border-color var(--transition), box-shadow var(--transition);
}

.cform__input::placeholder {
  color: rgba(150, 165, 200, 0.75);
}

.cform__input:hover {
  border-color: var(--color-border-bright);
}

.cform__input:focus {
  outline: none;
  border-color: var(--color-violet);
  box-shadow: 0 0 0 3px rgba(123, 70, 245, 0.28);
}

/* The selects and the textarea carry no leading icon in the reference's
   layout for selects, so they reclaim the padding. */
.cform__select {
  padding-left: clamp(0.85rem, 1.4vw, 1.1rem);
  padding-right: clamp(2.4rem, 3.2vw, 2.9rem);
  appearance: none;
  cursor: pointer;
}

.cform__select option {
  color: var(--color-text);
  background-color: #0a1024;
}

.cform__chevron {
  position: absolute;
  right: clamp(0.85rem, 1.4vw, 1.1rem);
  width: 1.15em;
  height: 1.15em;
  fill: none;
  stroke: var(--color-text-muted);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  pointer-events: none;
}

.cform__textarea {
  min-height: clamp(9rem, 16vw, 14rem);
  padding-top: clamp(0.85rem, 1.4vw, 1.1rem);
  line-height: 1.6;
  resize: vertical;
}

.cform__counter {
  margin-top: 0.4em;
  font-size: clamp(0.75rem, 0.73rem + 0.22vw, 0.9rem);
  color: var(--color-text-muted);
  text-align: right;
}

.cform__privacy {
  margin-bottom: clamp(1rem, 2vw, 1.5rem);
  font-size: clamp(0.78rem, 0.76rem + 0.28vw, 0.95rem);
  line-height: 1.6;
  color: var(--color-text-muted);
}

.cform__privacy a {
  color: var(--color-cyan);
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

.cform__privacy a:hover {
  color: var(--color-text);
}

.cform__submit {
  width: 100%;
}


/* --- 24.5 Attachment drop zone ----------------------------- */

/* The <label> is the drop zone, so a pointer click and a keyboard activation
   both reach the real file input inside it. */
.cdrop {
  display: flex;
  flex-direction: column;
  gap: 0.35em;
  align-items: center;
  justify-content: center;
  min-height: clamp(6.5rem, 11vw, 9.5rem);
  padding: clamp(1rem, 2vw, 1.75rem);
  text-align: center;
  background-color: rgba(8, 14, 32, 0.5);
  border: 1.5px dashed var(--color-border-bright);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background-color var(--transition), border-color var(--transition);
}

.cdrop:hover,
.cdrop.is-dragging {
  background-color: rgba(14, 23, 48, 0.78);
  border-color: var(--color-violet);
}

/* The input stays in the layout — never display:none — so it keeps its place in
   the tab order and the label's focus ring follows it. */
.cform__file {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.cform__file:focus-visible + *,
.cdrop:has(.cform__file:focus-visible) {
  outline: 2px solid var(--color-cyan);
  outline-offset: 3px;
}

.cdrop__icon {
  width: clamp(1.8rem, 3vw, 2.6rem);
  height: clamp(1.8rem, 3vw, 2.6rem);
  fill: none;
  stroke: var(--color-purple);
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.cdrop__text {
  font-size: clamp(0.875rem, 0.84rem + 0.4vw, 1.125rem);
  color: var(--color-text-bright);
}

.cdrop__cta {
  font-weight: 600;
  color: var(--color-cyan);
}

.cdrop__hint {
  font-size: clamp(0.75rem, 0.73rem + 0.25vw, 0.9375rem);
  color: var(--color-text-muted);
}

/* Chosen-file row */
.cfile {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5em 0.75em;
  align-items: center;
  margin-top: 0.75em;
  padding: 0.65em 0.9em;
  font-size: clamp(0.8rem, 0.78rem + 0.3vw, 1rem);
  color: var(--color-text-bright);
  background-color: var(--color-surface-soft);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.cfile__icon {
  width: 1.15em;
  height: 1.15em;
  flex-shrink: 0;
  fill: none;
  stroke: var(--color-cyan);
  stroke-width: 1.8;
  stroke-linejoin: round;
}

.cfile__name {
  min-width: 0;
  overflow-wrap: anywhere;
  font-weight: 600;
}

.cfile__size {
  color: var(--color-text-muted);
}

.cfile__remove {
  display: inline-flex;
  gap: 0.35em;
  align-items: center;
  margin-left: auto;
  padding: 0.35em 0.7em;
  font: inherit;
  font-size: 0.92em;
  color: var(--color-text-bright);
  background-color: rgba(8, 14, 32, 0.7);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: border-color var(--transition), color var(--transition);
}

.cfile__remove:hover {
  color: var(--color-text);
  border-color: var(--color-border-bright);
}

.cfile__remove svg {
  width: 0.9em;
  height: 0.9em;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
}


/* --- 24.6 Validation and status ---------------------------- */

/* `display` on these would otherwise beat the UA rule for [hidden] and keep
   them on screen while they are meant to be absent. */
.cform__error[hidden],
.cfile[hidden] {
  display: none;
}

/* Errors carry an icon and text, so the state is never colour alone. */
.cform__error {
  display: flex;
  gap: 0.4em;
  align-items: flex-start;
  margin-top: 0.45em;
  font-size: clamp(0.78rem, 0.76rem + 0.28vw, 0.95rem);
  line-height: 1.5;
  color: #ffa8c8;
}

.cform__error::before {
  content: "!";
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 1.2em;
  height: 1.2em;
  margin-top: 0.1em;
  font-size: 0.85em;
  font-weight: 700;
  color: #1a0a18;
  background-color: #ffa8c8;
  border-radius: 50%;
}

.cform__input[aria-invalid="true"] {
  border-color: #ff8ab6;
}

.cform__input[aria-invalid="true"]:focus {
  box-shadow: 0 0 0 3px rgba(255, 138, 182, 0.28);
}

.cdrop.is-invalid {
  border-color: #ff8ab6;
}

.cform__status {
  margin-top: clamp(0.9rem, 1.6vw, 1.35rem);
  padding: clamp(0.85rem, 1.6vw, 1.25rem) clamp(1rem, 1.8vw, 1.4rem);
  font-size: clamp(0.85rem, 0.82rem + 0.35vw, 1.0625rem);
  line-height: 1.65;
  color: var(--color-text-bright);
  background-color: var(--color-surface-soft);
  border: 1px solid var(--color-border-bright);
  border-radius: var(--radius-md);
}

.cform__status a {
  color: var(--color-cyan);
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

.cform__status strong {
  display: block;
  margin-bottom: 0.25em;
  color: var(--color-text);
}

.cform__status--problem {
  border-color: rgba(255, 138, 182, 0.55);
}


/* --- 24.7 Contact information ------------------------------ */

.cinfo {
  display: grid;
  gap: clamp(0.6rem, 1.1vw, 1rem);
  width: 100%;
  margin-top: clamp(1rem, 2vw, 1.6rem);
}

.cinfo__card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(0.75rem, 1.4vw, 1.15rem);
  align-items: center;
  padding: clamp(0.85rem, 1.5vw, 1.25rem);
  background-color: var(--color-surface-soft);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition: border-color var(--transition), box-shadow var(--transition);
}

.cinfo__card:hover,
.cinfo__card:focus-within {
  border-color: var(--color-border-bright);
  box-shadow: 0 0 22px rgba(59, 130, 246, 0.14);
}

.cinfo__icon {
  display: grid;
  place-items: center;
  width: clamp(2.6rem, 4vw, 3.75rem);
  aspect-ratio: 1;
  border-radius: 28%;
  box-shadow: 0 6px 18px rgba(8, 10, 30, 0.45);
}

.cinfo__icon svg {
  width: 54%;
  height: 54%;
  fill: #ffffff;
  stroke: none;
  color: #ffffff;
}

.cinfo__icon--violet {
  background-image: linear-gradient(145deg, #8b6bff 0%, #6d28f0 100%);
}

.cinfo__icon--blue {
  background-image: linear-gradient(145deg, #45c8fb 0%, #1f8fe8 100%);
}

.cinfo__body {
  display: flex;
  flex-direction: column;
  gap: 0.15em;
  min-width: 0;
}

.cinfo__label {
  font-size: clamp(0.78rem, 0.76rem + 0.28vw, 0.95rem);
  color: var(--color-text-muted);
}

.cinfo__value {
  font-size: clamp(0.9rem, 0.86rem + 0.4vw, 1.125rem);
  font-weight: 600;
  color: var(--color-text);
  overflow-wrap: anywhere;
}

.cinfo__value--link {
  color: var(--color-cyan);
  transition: color var(--transition);
}

.cinfo__value--link:hover {
  color: var(--color-text);
}


/* --- 24.8 Location map ------------------------------------- */

.cmap {
  position: relative;
  /* Contains the tint's blend mode to this card so it cannot reach the panel
     behind it. */
  isolation: isolate;
  overflow: hidden;
  width: 100%;
  margin-top: clamp(1rem, 2vw, 1.6rem);
  /* Must stay equal to the embed bbox aspect, or OpenStreetMap letterboxes the
     tiles and the centred pin no longer lands on the centre point. */
  aspect-ratio: 4 / 3;
  background-color: var(--color-surface-soft);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

/* Sits behind the frame. If the embed is blocked or fails to load, this is
   simply what remains visible, so the card is never an empty rectangle. */
.cmap__fallback {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5em;
  align-items: center;
  justify-content: center;
  font-size: clamp(0.85rem, 0.82rem + 0.35vw, 1.0625rem);
  color: var(--color-text-bright);
}

.cmap__fallback svg {
  width: clamp(1.6rem, 2.6vw, 2.25rem);
  height: clamp(1.6rem, 2.6vw, 2.25rem);
  color: var(--color-cyan);
}

/* The keyless OpenStreetMap embed only ships a light tile set, so the dark
   theme is applied here rather than bought from a dark-tile provider. Two
   steps: invert to turn the paper-white tiles dark and drop most of the
   original hue, then tint the result to the site's navy. */
/* The dark treatment sits on this wrapper, never on the iframe itself. A CSS
   filter applied directly to an iframe makes Chromium lay the embedded document
   out at a stale, smaller size: the map stopped filling the card and the
   remainder showed the embed's own page background, inverted to black. */
.cmap__shade {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: block;
  /* Contrast is what sets the marker's lightness. The tint below contributes
     only hue, so its own lightness cannot reach the pin; the pin is instead the
     brightest thing in the frame once the tiles are inverted, so raising
     contrast lifts it while pushing the tiles further down. saturate keeps it
     vivid at that lightness. */
  filter: invert(0.93) brightness(0.8) contrast(1.6) saturate(1.35);
}

.cmap__frame {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Recolours the inverted tiles, and with them OpenStreetMap's marker, which
   sits inside the iframe and cannot be styled directly. A hue blend applies one
   hue to everything, so this single value sets both: the tiles are nearly
   desaturated and read as dark violet-navy, while the marker keeps its own high
   saturation and comes out as this violet. Change this to move the pin.
   Deliberately a literal rather than --color-violet: this is the exact marker
   colour that was specified, and it should not drift if that token changes. */
.cmap__tint {
  position: absolute;
  inset: 0;
  z-index: 2;
  background-color: #6d47f0;
  /* `hue`, not `color`: it takes only the hue from this layer and leaves the
     backdrop's saturation and luminosity alone. That matters because the marker
     lives inside the iframe and is tinted along with the tiles — under `color`
     it was flattened to the same muted navy as the map and became impossible to
     find, whereas here it keeps its own high saturation and still reads as a
     distinct pin. */
  mix-blend-mode: hue;
  pointer-events: none;
}

/* A second pass in the surface colour settles the midtones onto the same navy
   the panels use. The filter above no longer desaturates, so this is what keeps
   the tiles down at panel brightness. */
.cmap__tint::after {
  content: "";
  position: absolute;
  inset: 0;
  background-color: var(--color-surface);
  opacity: 0.42;
  mix-blend-mode: multiply;
}

/* Top-left rather than bottom-left: OpenStreetMap paints its required
   attribution along the bottom edge of the embed, inside the iframe where it
   cannot be restyled, and the two collided there. */
.cmap__chip {
  position: absolute;
  z-index: 3;
  top: 0.6rem;
  left: 0.6rem;
  display: flex;
  gap: 0.4em;
  align-items: center;
  padding: 0.4em 0.75em;
  font-size: clamp(0.75rem, 0.73rem + 0.25vw, 0.9375rem);
  color: var(--color-text);
  background-color: rgba(6, 10, 24, 0.86);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  backdrop-filter: blur(4px);
  pointer-events: none;
}

.cmap__chip svg {
  width: 1.05em;
  height: 1.05em;
  color: var(--color-cyan);
}


/* --- 24.9 Why contact us ----------------------------------- */

.why {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(1.25rem, 2.6vw, 2.5rem);
  align-items: center;
  margin-top: clamp(1rem, 2vw, 1.5rem);
  padding: clamp(1.4rem, 2.6vw, 2.5rem) clamp(1.25rem, 2.2vw, 2.25rem);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.why__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.why__title {
  margin-top: clamp(0.75rem, 1.4vw, 1.25rem);
  font-size: clamp(1.4rem, 1rem + 1.7vw, 2.75rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.why__lead {
  max-width: 34rem;
  margin-top: clamp(0.5rem, 1vw, 0.9rem);
  font-size: clamp(0.875rem, 0.84rem + 0.4vw, 1.1875rem);
  line-height: 1.65;
  color: var(--color-text-muted);
  text-wrap: pretty;
}

.why__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(0.6rem, 1.1vw, 1rem);
}

.why__card {
  display: flex;
  flex-direction: column;
  gap: clamp(0.5rem, 1vw, 0.85rem);
  align-items: center;
  padding: clamp(0.9rem, 1.7vw, 1.5rem) clamp(0.6rem, 1.1vw, 1rem);
  text-align: center;
  background-color: var(--color-surface-soft);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition: border-color var(--transition), box-shadow var(--transition);
}

.why__card:hover {
  border-color: var(--color-border-bright);
  box-shadow: 0 0 22px rgba(59, 130, 246, 0.14);
}

/* Reuses the homepage value-icon ring and accents; only the size differs. */
.why__icon {
  width: clamp(2.6rem, 4.2vw, 4rem);
  margin-bottom: 0;
}

.why__card-title {
  font-size: clamp(0.85rem, 0.8rem + 0.42vw, 1.125rem);
  font-weight: 700;
  line-height: 1.3;
  text-wrap: balance;
}


/* --- 24.10 FAQ --------------------------------------------- */

.faq {
  margin-top: clamp(1rem, 2vw, 1.5rem);
  padding: clamp(1.4rem, 2.6vw, 2.5rem) clamp(1.25rem, 2.2vw, 2.25rem);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.faq__head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.faq__title {
  margin-top: clamp(0.75rem, 1.4vw, 1.25rem);
  font-size: clamp(1.3rem, 1rem + 1.5vw, 2.5rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.faq__lead {
  margin-top: clamp(0.4rem, 0.8vw, 0.7rem);
  font-size: clamp(0.875rem, 0.84rem + 0.4vw, 1.1875rem);
  color: var(--color-text-muted);
}

.faq__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(0.6rem, 1.1vw, 1rem);
  margin-top: clamp(1.25rem, 2.4vw, 2rem);
}

.faq__card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(0.6rem, 1.1vw, 1rem);
  align-items: start;
  padding: clamp(0.9rem, 1.7vw, 1.5rem);
  background-color: var(--color-surface-soft);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition: border-color var(--transition), box-shadow var(--transition);
}

.faq__card:hover {
  border-color: var(--color-border-bright);
  box-shadow: 0 0 22px rgba(59, 130, 246, 0.14);
}

.faq__mark {
  display: grid;
  place-items: center;
  width: clamp(1.7rem, 2.6vw, 2.4rem);
  aspect-ratio: 1;
  color: var(--color-purple);
  background-color: rgba(124, 58, 237, 0.16);
  border-radius: 50%;
}

.faq__mark svg {
  width: 68%;
  height: 68%;
}

.faq__q {
  font-size: clamp(0.85rem, 0.82rem + 0.35vw, 1.0625rem);
  font-weight: 600;
  line-height: 1.4;
  color: var(--color-text);
  text-wrap: pretty;
}

.faq__a {
  margin-top: 0.45em;
  font-size: clamp(0.8rem, 0.78rem + 0.32vw, 1rem);
  line-height: 1.6;
  color: var(--color-text-muted);
  text-wrap: pretty;
}


/* --- 24.11 Contact responsive behaviour -------------------- */

@media (max-width: 1024px) {
  /* The flourish sits in the hero's right margin; below this the copy needs
     that width. */
  .contact-flourish {
    display: none;
  }

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

@media (max-width: 900px) {
  /* Form first, then contact details and the map, as in the reference's
     stacked reading order. */
  .contact-main,
  .why {
    grid-template-columns: minmax(0, 1fr);
  }

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

}

@media (max-width: 620px) {
  .cform__row {
    grid-template-columns: minmax(0, 1fr);
  }

  .faq__grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .cfile__remove {
    margin-left: 0;
  }
}

@media (max-width: 420px) {
  .why__grid {
    grid-template-columns: minmax(0, 1fr);
  }
}


/* =========================================================
   25. PixelOrbit Studio Apps Page
   ---------------------------------------------------------
   Scoped to .page-apps, or to class names used on that page
   alone. The header, footer, buttons, breadcrumb, pill,
   accent heading, hero flourish, script lettering, value
   cards and the CTA panel are all reused as-is.

   The showcase, the icon system and the phone frame are
   written as components rather than as Nebula Notes styling:
   a second app is a second .app-showcase and needs no new
   CSS.

   25.1  Apps page base
   25.2  Apps hero
   25.3  Rounded-square app icons
   25.4  Featured app showcase
   25.5  Feature row and actions
   25.6  Phone frame
   25.7  More apps coming soon
   25.8  Our approach
   25.9  Apps responsive behaviour
   ========================================================= */


/* --- 25.1 Apps page base ----------------------------------- */

/* The artwork is 16:9 and object-fit: cover is width-constrained here, so the
   band's aspect ratio decides how much of the picture survives. The reference
   band is a little over 2.2:1, which keeps the galaxy, the ridge line and the
   lake in frame while leaving the left third dark enough for the copy. 46vw
   holds that ratio as the frame widens; the cap matches the 2560px container,
   and below ~800px the floor takes over, because a band 46% of a phone's width
   would be far too shallow to seat the hero copy. */
.page-apps {
  --sky-height: clamp(23rem, 46vw, 82rem);
}

.sky--apps {
  object-position: center 47%;
}

/* Darkens the left, where the breadcrumb, headings and body sit, and blends the
   artwork into the page before the featured panel begins. Localised rather than
   a flat scrim, so the galaxy, mountains and lake keep their colour. */
.sky__fade--apps {
  background:
    linear-gradient(
      to bottom,
      rgba(5, 7, 15, 0.55) 0%,
      rgba(5, 7, 15, 0.18) 22%,
      rgba(7, 11, 26, 0.12) 56%,
      rgba(7, 11, 26, 0.7) 87%,
      var(--color-bg) 100%
    ),
    linear-gradient(
      100deg,
      rgba(4, 6, 16, 0.9) 0%,
      rgba(4, 6, 16, 0.62) 30%,
      rgba(4, 6, 16, 0.14) 56%,
      rgba(4, 6, 16, 0) 70%
    );
}


/* --- 25.2 Apps hero ---------------------------------------- */

/* Same construction as the About, Terms and privacy heroes: --pad-x so the
   breadcrumb, headings and body line up with the header's brand and with the
   panels below, and a min-height so the band the reader sees holds the ratio
   above instead of collapsing once the type hits its clamp ceilings. */
.apps-hero {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: calc(var(--sky-height) - var(--header-height) - var(--pad-frame));
  padding: clamp(1.25rem, 2.4vw, 2.5rem) var(--pad-x) clamp(2.5rem, 6vw, 6rem);
}

.apps-hero__title {
  /* Optical alignment: Outfit's left side bearing is about 0.057em, so at this
     size the ink would start ~5px inside the box while the breadcrumb and
     tagline start ~1px in. */
  margin-left: -0.045em;
  margin-top: clamp(1rem, 2.4vw, 2rem);
  font-size: clamp(2.5rem, 1rem + 6.2vw, 6rem);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.025em;
}

/* Second line of the same heading, so the pair reads as one title to assistive
   technology. .accent-gradient paints it, and falls back to flat pink where
   background-clip: text is unsupported. */
.apps-hero__accent {
  display: block;
}

.apps-hero__tagline {
  margin-top: clamp(1rem, 2.2vw, 1.75rem);
  font-size: clamp(1.05rem, 0.95rem + 0.62vw, 1.625rem);
  font-weight: 600;
  color: var(--color-text);
}

.apps-hero__lead {
  max-width: 34rem;
  margin-top: clamp(0.9rem, 1.8vw, 1.5rem);
  font-size: clamp(0.95rem, 0.9rem + 0.5vw, 1.3125rem);
  line-height: 1.75;
  color: var(--color-text-bright);
  text-wrap: pretty;
}


/* --- 25.3 Rounded-square app icons ------------------------- */

/* The reference draws every icon on this page as a rounded square rather than
   the disc used elsewhere, so this is its own component instead of an override
   of .value__icon. Fill and ink come from one modifier each, so a new accent is
   a single line. --app-icon-size lets a context resize it without touching the
   modifiers. */
.app-icon {
  display: grid;
  place-items: center;
  width: var(--app-icon-size, clamp(2.9rem, 5.4vw, 5rem));
  aspect-ratio: 1;
  margin-bottom: clamp(0.7rem, 1.5vw, 1.15rem);
  color: var(--app-icon-ink);
  background-image: var(--app-icon-fill);
  border-radius: 28%;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.07);
  transition: filter var(--transition), box-shadow var(--transition);
}

.app-icon svg {
  width: 52%;
  height: 52%;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Translucent tints, used where the tile sits on the featured panel and should
   read as a wash over the artwork behind it. */
.app-icon--pink-soft   { --app-icon-fill: linear-gradient(150deg, rgba(232, 121, 249, 0.26) 0%, rgba(168, 85, 247, 0.12) 100%); --app-icon-ink: var(--color-pink); }
.app-icon--violet-soft { --app-icon-fill: linear-gradient(150deg, rgba(139, 107, 255, 0.3) 0%, rgba(76, 63, 240, 0.14) 100%);  --app-icon-ink: var(--color-magenta); }
.app-icon--cyan-soft   { --app-icon-fill: linear-gradient(150deg, rgba(56, 189, 248, 0.26) 0%, rgba(34, 211, 238, 0.1) 100%);  --app-icon-ink: var(--color-cyan); }
.app-icon--teal-soft   { --app-icon-fill: linear-gradient(150deg, rgba(45, 212, 191, 0.26) 0%, rgba(34, 211, 238, 0.1) 100%);  --app-icon-ink: var(--color-teal); }

/* Opaque fills, used on the cards, where the tile is the card's one point of
   colour. */
.app-icon--violet    { --app-icon-fill: linear-gradient(150deg, #9061f9 0%, #6d28d9 100%); --app-icon-ink: #f1e6ff; }
.app-icon--magenta   { --app-icon-fill: linear-gradient(150deg, #a855f7 0%, #7126d6 100%); --app-icon-ink: #f9b4ef; }
.app-icon--indigo    { --app-icon-fill: linear-gradient(150deg, #12406f 0%, #0b2245 100%); --app-icon-ink: var(--color-cyan); }
.app-icon--deep-cyan { --app-icon-fill: linear-gradient(150deg, #0f4467 0%, #0a2340 100%); --app-icon-ink: var(--color-cyan); }
/* Brighter than --deep-cyan, sampled from the privacy reference's section tiles
   (#12729f to #00527f). Both are needed: the Apps cards sit on a lighter card
   surface and want the darker tile, the privacy sections sit on the panel
   surface and want this one. */
.app-icon--cyan      { --app-icon-fill: linear-gradient(150deg, #12729f 0%, #00527f 100%); --app-icon-ink: var(--color-cyan); }

/* Matches the lift the value discs get on the About page. Presentational only —
   the cards stay non-interactive, so there is no pointer cursor and nothing to
   activate. */
.about-vcard:hover .app-icon,
.soon-card:hover .app-icon {
  filter: brightness(1.12);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14), 0 0 22px rgba(124, 92, 240, 0.32);
}


/* --- 25.4 Featured app showcase ---------------------------- */

.apps-featured {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  margin-top: clamp(1rem, 2vw, 1.5rem);
  padding: clamp(1.75rem, 3.2vw, 3.25rem) var(--pad-x);
  /* The reference sets this panel in space: a violet pool behind the phone and
     a cooler one behind the copy. Gradients rather than an image — no artwork
     was supplied for the panel itself, and this costs nothing to load. */
  background-color: var(--color-surface);
  background-image:
    radial-gradient(58% 68% at 76% 46%, rgba(124, 92, 240, 0.22) 0%, rgba(124, 92, 240, 0) 72%),
    radial-gradient(72% 90% at 6% 0%, rgba(37, 99, 235, 0.16) 0%, rgba(37, 99, 235, 0) 66%);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.app-showcase {
  display: grid;
  /* The reference gives the copy about 63% of the panel and the phone the rest. */
  grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 3vw, 3rem);
  /* stretch, not center: in the reference the copy column spans the phone's
     full height rather than floating in the middle of it. */
  align-items: stretch;
  width: 100%;
  margin-top: clamp(1.25rem, 2.6vw, 2.25rem);
}

/* A second app in this section is a second .app-showcase; this is the only rule
   it needs, and it separates the pair without reordering anything. */
.app-showcase + .app-showcase {
  margin-top: clamp(2rem, 4vw, 3.5rem);
  padding-top: clamp(2rem, 4vw, 3.5rem);
  border-top: 1px solid var(--color-border);
}

.app-showcase__main {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* The margins below are the minimum spacing; any height the phone adds beyond
     that is shared between the three blocks, which is how the reference sits
     the name near the top of the panel and the buttons near the bottom. */
  justify-content: space-between;
}

.app-showcase__head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(1rem, 2.2vw, 2rem);
  align-items: center;
  width: 100%;
}

/* The official icon, scaled by CSS only — the artwork itself is untouched. The
   ring reproduces the reference's edge. */
.app-showcase__icon {
  width: clamp(4.75rem, 11vw, 11rem);
  height: auto;
  border-radius: 24%;
  box-shadow: 0 0 0 1.5px rgba(244, 114, 208, 0.7), 0 12px 30px rgba(8, 10, 30, 0.6);
}

.app-showcase__name {
  font-size: clamp(1.3rem, 1rem + 1.55vw, 3rem);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.015em;
}

.app-showcase__slogan {
  margin-top: 0.3rem;
  font-size: clamp(0.95rem, 0.88rem + 0.52vw, 1.5rem);
  font-weight: 600;
}

.app-showcase__text {
  max-width: 34rem;
  margin-top: 0.6rem;
  font-size: clamp(0.9rem, 0.85rem + 0.45vw, 1.25rem);
  line-height: 1.6;
  color: var(--color-text-bright);
  text-wrap: pretty;
}


/* --- 25.5 Feature row and actions -------------------------- */

.app-features {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(1.25rem, 2.4vw, 2rem) clamp(0.5rem, 1.4vw, 1rem);
  width: 100%;
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
}

.app-feature {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.app-feature__title {
  font-size: clamp(0.875rem, 0.8rem + 0.44vw, 1.25rem);
  font-weight: 700;
  line-height: 1.3;
}

.app-feature__text {
  max-width: 13rem;
  margin-top: 0.35rem;
  font-size: clamp(0.8125rem, 0.78rem + 0.34vw, 1.0625rem);
  line-height: 1.5;
  color: var(--color-text-muted);
  text-wrap: balance;
}

.app-showcase__actions {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(0.85rem, 1.8vw, 1.5rem);
  align-items: center;
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
}

/* .play-badge carries a top margin for the product page, where it sits under a
   paragraph. Here it is a flex item and the row's own gap does the spacing, so
   the margin would only push it out of line with the button beside it. The
   width is also reset: 30vw is right for a full-width column, far too wide for
   half a panel. */
.app-showcase__play {
  width: clamp(9.5rem, 17vw, 18rem);
  margin-top: 0;
}


/* --- 25.6 Featured device ---------------------------------- */

.app-showcase__visual {
  display: flex;
  gap: clamp(0.5rem, 1.6vw, 1.5rem);
  align-items: center;
  justify-content: center;
}

/* The supplied device frame composited over the supplied splash screenshot.
   The two stay separate files so the screen artwork can be replaced later
   without touching the device.

   Measured from nebula-notes-phone-frame.png (941 x 1672): the display aperture
   is genuinely transparent, and it is a perspective quadrilateral rather than a
   rectangle — the device is drawn very slightly off-axis with its right edge
   nearer, so the aperture's bottom edge falls 1.72 degrees to the right while
   its top edge stays level, and the right side stands 1.5% taller than the
   left. The frame's notch, speaker, camera and bezel are opaque, so the frame
   layers over the screenshot and no part of the device has to be redrawn.

   The device itself occupies 81.9% of the asset's width, the rest being its
   own transparent margin, so --phone-w is about a fifth larger than the device
   the reader actually sees. */
.apps-phone {
  --phone-w: clamp(20rem, 25.5vw, 28rem);
  position: relative;
  flex: none;
  width: var(--phone-w);
  /* Stated as well as carried by the frame's width/height attributes, so the
     screen is positioned correctly even before the frame decodes. */
  aspect-ratio: 941 / 1672;
  /* The asset already carries its own violet edge lighting, so this is only
     enough to seat the device against the panel. drop-shadow rather than
     box-shadow: it follows the device's silhouette instead of its bounding
     box, which here is mostly transparent margin. */
  filter:
    drop-shadow(0 calc(var(--phone-w) * 0.03) calc(var(--phone-w) * 0.05) rgba(4, 6, 18, 0.55))
    drop-shadow(0 0 calc(var(--phone-w) * 0.035) rgba(124, 92, 240, 0.26));
}

/* The screen plane, tilted onto the aperture's quadrilateral.

   An axis-aligned screenshot in a perspective aperture is what makes a mockup
   look pasted on: the home indicator and the lines of type stay dead level
   while the bezel around them falls away, and the eye reads the two as separate
   objects. So the plane is turned to sit in the device instead.

   The rotation and the rectangle below are fitted to the four aperture corners
   rather than guessed. Turning the right edge towards the viewer scales that
   side up about a horizontal axis, so the pivot is what sets the tilt: at 14%
   down the display, the top edge comes out level and the bottom falls 1.72
   degrees, which is the aperture's own geometry. The rectangle is then the
   pre-image of the aperture under that projection — insets a little different
   from the aperture's own, and a shade generous on every side so the corners
   stay covered; the overhang is behind opaque bezel. Projected back, this lands
   on the measured bottom edge to within a tenth of a pixel across its width. */
.apps-phone__screen {
  position: absolute;
  top: 4.15%;
  right: 15%;
  bottom: 4.7%;
  left: 15.75%;
  overflow: hidden;
  /* Squarer than the aperture's own 66px corners on purpose: the frame does the
     real rounding, and running wide here guarantees no sliver of bezel-coloured
     gap appears inside it. */
  border-radius: 8.5% / 3.6%;
  /* The splash's own top-edge colour, so the inset below reads as screen rather
     than as a gap. */
  background-color: #09071d;
  transform: perspective(calc(var(--phone-w) * 4.84)) rotateY(-6deg);
  transform-origin: 50% 14%;
}

/* Seated 3% down the display rather than flush with its top.

   The screenshot was taken on a device with a shallower notch than this frame
   has, so its status bar sits high enough that the frame's corner radius cuts
   into the clock — at the top of those glyphs the bezel reaches 44px into the
   aperture, and no choice of object-fit moves them clear. Dropping the image by
   3% both clears the corner and centres the status bar against this frame's
   deeper notch, which is where it would sit on this device. The 3% it gives up
   at the top is the panel's background colour above, indistinguishable from the
   screenshot's own.

   The aperture is 0.4245 and the screenshot 0.45, so cover still trims about
   1.4% from each side — empty margin either side of the status bar, nowhere
   near the artwork — rather than letterboxing or stretching the screenshot. */
.apps-phone__screen img {
  position: absolute;
  top: 3%;
  left: 0;
  width: 100%;
  height: 97%;
  object-fit: cover;
}

/* Left in flow, so the wrapper takes its height from the asset. Above the
   screen, so the notch, speaker, camera and bezel all read as one device. */
.apps-phone__frame {
  position: relative;
  z-index: 1;
  width: 100%;
  height: auto;
  pointer-events: none;
}

.app-showcase__decor {
  flex: none;
  width: clamp(5rem, 9.5vw, 12rem);
  pointer-events: none;
}

.app-showcase__script {
  font-size: clamp(0.95rem, 1.7vw, 2.1rem);
  transform: rotate(-5deg);
}


/* --- 25.7 More apps coming soon ---------------------------- */

.soon {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  margin-top: clamp(1rem, 2vw, 1.5rem);
  padding: clamp(1.75rem, 3.2vw, 3.25rem) var(--pad-x);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.soon__title,
.approach__title {
  font-size: clamp(1.6rem, 1rem + 2.5vw, 3.5rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.soon__lead,
.approach__lead {
  max-width: 48rem;
  margin-top: clamp(0.5rem, 1vw, 0.9rem);
  font-size: clamp(0.9rem, 0.86rem + 0.42vw, 1.25rem);
  line-height: 1.6;
  color: var(--color-text-muted);
  text-wrap: pretty;
}

.soon__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1rem, 2vw, 1.75rem);
  width: 100%;
  margin-top: clamp(1.5rem, 2.8vw, 2.5rem);
}

/* Categories the studio is working towards, not announced products: no names,
   no dates and nothing to click. A real release graduates into an
   .app-showcase in the section above. */
.soon-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: clamp(1.25rem, 2.4vw, 2.25rem) clamp(1rem, 1.8vw, 1.75rem);
  background-color: var(--color-surface-soft);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition: border-color var(--transition), box-shadow var(--transition);
}

.soon-card:hover {
  border-color: var(--color-border-bright);
  box-shadow: 0 0 26px rgba(59, 130, 246, 0.14);
}

.soon-card__icon {
  --app-icon-size: clamp(3.4rem, 6.4vw, 6rem);
}

.soon-card__title {
  font-size: clamp(0.95rem, 0.85rem + 0.55vw, 1.4375rem);
  font-weight: 700;
  line-height: 1.3;
}

.soon-card__status {
  margin-top: 0.1rem;
  font-size: clamp(0.95rem, 0.85rem + 0.52vw, 1.4375rem);
  font-weight: 700;
  line-height: 1.3;
  color: var(--color-cyan);
}

.soon-card__text {
  max-width: 15rem;
  margin-top: clamp(0.6rem, 1.2vw, 1rem);
  /* Floor under the description: the marker below is pushed down by an auto
     margin, which can only add to this gap, never close it up. */
  margin-bottom: clamp(0.9rem, 1.8vw, 1.5rem);
  font-size: clamp(0.875rem, 0.82rem + 0.45vw, 1.1875rem);
  line-height: 1.5;
  color: var(--color-text-muted);
  text-wrap: balance;
}

/* A status marker, not a control. It is a paragraph rather than a button or a
   disabled link because there is nothing to open yet, and a disabled-looking
   control would invite clicks that can never do anything. */
.soon-card__tag {
  /* auto rather than a fixed gap: the cards stretch to the tallest in the row,
     and the reference lines the three markers up with each other rather than
     hanging each one a fixed distance under a description that may run to one
     line or two. */
  margin-top: auto;
  padding: 0.35em 1.35em;
  font-size: clamp(0.8125rem, 0.78rem + 0.3vw, 1.0625rem);
  font-weight: 500;
  line-height: 1.4;
  color: var(--color-text);
  background-color: rgba(10, 16, 36, 0.55);
  border: 1px solid var(--color-border-accent);
  border-radius: var(--radius-pill);
}


/* --- 25.8 Our approach ------------------------------------- */

.approach {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  margin-top: clamp(1rem, 2vw, 1.5rem);
  padding: clamp(1.75rem, 3.2vw, 3.25rem) var(--pad-x);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

/* The About page's value grid and card shell, unchanged; only the icon inside
   each card differs, and that is .app-icon's own doing. */
.approach__grid {
  width: 100%;
  margin-top: clamp(1.5rem, 2.8vw, 2.5rem);
}


/* --- 25.9 Apps responsive behaviour ------------------------ */

/* The hero flourish is already dropped below 1024px by the About page's rule,
   which is not scoped to that page — the copy needs the hero's full width at
   that size, on either page. */

@media (max-width: 1100px) {
  /* Copy first, phone after, as in the reference's stacked reading order. */
  .app-showcase {
    grid-template-columns: minmax(0, 1fr);
  }

  .app-showcase__visual {
    margin-top: clamp(1.25rem, 4vw, 2rem);
  }

  /* Stacked, the visual has the panel's full width instead of a third of it,
     so the device is no longer competing with the copy for it. */
  .apps-phone {
    --phone-w: min(22rem, 52vw);
  }
}

@media (max-width: 900px) {
  .app-features {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

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

  /* Both calls to action span the row rather than sitting side by side at
     half width, where the badge artwork would shrink below legibility. */
  .app-showcase__play {
    width: min(100%, 15rem);
  }
}

@media (max-width: 620px) {
  /* Below this the icon and the name beside it leave the name about eight
     characters of width, so the pair stacks and centres. */
  .app-showcase__head {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    text-align: center;
  }

  .app-showcase__text {
    margin-inline: auto;
  }

  .soon__grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .app-showcase__more {
    width: 100%;
  }

  /* Everything else in this column is centred at this width — the icon, the
     name, the description, the feature tiles. The badge was the one item still
     pinned to the left edge, because it is narrower than its row and the row
     was left-aligned.

     The extra top margin separates the two calls to action from the feature
     tiles above: the previous 24px was barely wider than the 20px gap between
     the tiles themselves, so the buttons read as a fifth row of the grid
     rather than as the place where the section asks you to act. */
  .app-showcase__actions {
    justify-content: center;
    margin-top: clamp(2.25rem, 5vw, 3rem);
  }

  /* The script lettering sits beside the phone, and below this the pair has to
     share about 20rem — which leaves the phone too small to make out. The phone
     is the content here and the script is decoration, so the decoration goes
     and the phone takes the width back. */
  .app-showcase__decor {
    display: none;
  }

  /* Centred under the copy and capped so the device never outgrows the
     panel's content width: 72vw clears the frame, body and panel padding at
     every width down to 320px, and 20rem is the ceiling on larger phones. */
  .apps-phone {
    --phone-w: min(20rem, 72vw);
  }
}

@media (max-width: 380px) {
  .app-features {
    grid-template-columns: minmax(0, 1fr);
  }

  .app-feature__text {
    max-width: none;
  }

  .soon-card__text {
    max-width: none;
  }
}


/* =========================================================
   26. PixelOrbit Studio General Privacy Policy
   ---------------------------------------------------------
   The studio-wide website policy at /privacy/, scoped to
   .pixelorbit-privacy-page or to gp- class names used on that
   page alone. The Nebula Notes app policy at
   /privacy/nebula-notes/ keeps section 21 and is untouched:
   it already owns .privacy-hero and the .policy-card /
   .policy-dialog system, which is why nothing here reuses
   those names.

   Reused as-is: the frame, header, footer, breadcrumb,
   buttons, .accent-gradient, the hero flourish
   (.about-flourish / .about-script / .about-comet), the
   value-card system for At a Glance, and .app-icon for every
   icon tile.

   26.1  General privacy page base
   26.2  Privacy hero
   26.3  Banner panels
   26.4  At a Glance
   26.5  Policy column and sections
   26.6  Policy lists
   26.7  Policy contact rows
   26.8  Privacy responsive behaviour
   26.9  Print
   ========================================================= */


/* --- 26.1 General privacy page base ------------------------ */

/* The artwork is 16:9 and object-fit: cover is width-constrained here, so the
   band's aspect ratio decides how much of the picture survives.

   A rem term is added to the vw term rather than using a plain vw ramp. This
   hero carries four blocks — breadcrumb, two-line title, date and lead — and
   at the bottom of the desktop range the type is near its clamp ceiling while
   vw is still small, so a plain ramp left the copy hanging below the artwork
   at around 1024-1280px. Measured against the real rendered copy, this holds
   the band deeper than the content at every width from 320 to 2560. */
.pixelorbit-privacy-page {
  --sky-height: clamp(32rem, 30vw + 18rem, 74rem);
}

.sky--gprivacy {
  object-position: center 46%;
}

/* Darkens the left, where the breadcrumb, headings and body sit, and blends the
   artwork into the page before the commitment panel begins. */
.sky__fade--gprivacy {
  background:
    linear-gradient(
      to bottom,
      rgba(5, 7, 15, 0.55) 0%,
      rgba(5, 7, 15, 0.18) 22%,
      rgba(7, 11, 26, 0.12) 54%,
      rgba(7, 11, 26, 0.72) 86%,
      var(--color-bg) 100%
    ),
    linear-gradient(
      100deg,
      rgba(4, 6, 16, 0.92) 0%,
      rgba(4, 6, 16, 0.66) 30%,
      rgba(4, 6, 16, 0.16) 56%,
      rgba(4, 6, 16, 0) 70%
    );
}


/* --- 26.2 Privacy hero ------------------------------------- */

/* Same construction as the About, Terms, Apps and app-policy heroes: --pad-x so
   the breadcrumb, headings and body line up with the header's brand and with
   the panels below, and a min-height so the band the reader sees holds the
   ratio above instead of collapsing once the type hits its clamp ceilings. */
.gp-hero {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: calc(var(--sky-height) - var(--header-height) - var(--pad-frame));
  padding: clamp(1.25rem, 2.4vw, 2.5rem) var(--pad-x) clamp(2rem, 4.5vw, 4.5rem);
}

.gp-hero__title {
  /* Optical alignment: Outfit's left side bearing is about 0.057em, so at this
     size the ink would start ~5px inside the box while the breadcrumb and date
     start ~1px in. */
  margin-left: -0.045em;
  margin-top: clamp(0.9rem, 2vw, 1.75rem);
  font-size: clamp(2.1rem, 0.9rem + 5.2vw, 5rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.025em;
}

/* Second line of the same heading, so the pair reads as one title to assistive
   technology. .accent-gradient paints it, falling back to flat pink where
   background-clip: text is unsupported. */
.gp-hero__brand {
  display: block;
}

.gp-hero__updated {
  margin-top: clamp(0.7rem, 1.5vw, 1.2rem);
  font-size: clamp(0.85rem, 0.8rem + 0.34vw, 1.125rem);
  font-weight: 500;
  color: var(--color-text-bright);
}

.gp-hero__lead {
  max-width: 32rem;
  margin-top: clamp(0.8rem, 1.6vw, 1.35rem);
  font-size: clamp(0.9rem, 0.86rem + 0.42vw, 1.1875rem);
  line-height: 1.7;
  color: var(--color-text-bright);
  text-wrap: pretty;
}


/* --- 26.3 Banner panels ------------------------------------ */

/* The Our Commitment panel and the closing panel are one component: icon tile,
   heading, one paragraph, cyan-edged surface. Nothing in either is
   interactive, so neither carries a hover state or a pointer cursor. */
.gp-banner {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(1rem, 2.2vw, 1.85rem);
  align-items: center;
  margin-top: clamp(1rem, 2vw, 1.5rem);
  padding: clamp(1.15rem, 2.2vw, 2rem) clamp(1.15rem, 2.2vw, 2.25rem);
  background:
    linear-gradient(115deg, rgba(34, 211, 238, 0.07) 0%, rgba(34, 211, 238, 0.02) 55%, rgba(10, 16, 36, 0) 100%),
    var(--color-surface);
  border: 1px solid rgba(56, 189, 248, 0.38);
  border-radius: var(--radius-lg);
}

.gp-banner__icon {
  --app-icon-size: clamp(3rem, 5.4vw, 4.75rem);
  margin-bottom: 0;
}

.gp-banner__title {
  font-size: clamp(1.15rem, 0.95rem + 0.95vw, 2.125rem);
  font-weight: 700;
  line-height: 1.25;
}

.gp-banner__title--cyan {
  color: var(--color-cyan);
}

.gp-banner__text {
  max-width: 62rem;
  margin-top: 0.35em;
  font-size: clamp(0.9rem, 0.86rem + 0.42vw, 1.1875rem);
  line-height: 1.6;
  color: var(--color-text-bright);
  text-wrap: pretty;
}

.gp-banner--closing {
  margin-top: clamp(1rem, 2vw, 1.5rem);
  border-color: rgba(56, 189, 248, 0.55);
}


/* --- 26.4 At a Glance -------------------------------------- */

.gp-glance {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  margin-top: clamp(1.25rem, 2.6vw, 2.25rem);
  padding-inline: var(--pad-x);
}

.gp-glance__title {
  font-size: clamp(1.4rem, 1rem + 1.9vw, 2.75rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.gp-glance__lead {
  max-width: 48rem;
  margin-top: clamp(0.35rem, 0.8vw, 0.7rem);
  font-size: clamp(0.875rem, 0.84rem + 0.4vw, 1.1875rem);
  line-height: 1.6;
  color: var(--color-text-muted);
  text-wrap: pretty;
}

.gp-glance__grid {
  width: 100%;
  margin-top: clamp(1rem, 2.2vw, 1.75rem);
}


/* --- 26.5 Policy column and sections ----------------------- */

/* One column, always. Every numbered section is a sibling here and nothing
   inside it changes that: no two-column legal layout, no masonry, no paired
   sections. The page is allowed to be long. */
.gp-policy {
  display: flex;
  flex-direction: column;
  gap: clamp(0.65rem, 1.1vw, 1.125rem);
  margin-top: clamp(1.25rem, 2.6vw, 2.25rem);
}

.gp-section {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(0.9rem, 1.9vw, 1.6rem);
  align-items: start;
  padding: clamp(1.1rem, 2vw, 1.9rem) clamp(1.15rem, 2.2vw, 2.25rem);
  background-color: var(--color-surface);
  border: 1px solid rgba(56, 189, 248, 0.26);
  border-radius: var(--radius-lg);
}

/* Supporting, not dominant: the tile helps the eye find the start of a section
   and then gets out of the way of the prose. */
.gp-section__icon {
  --app-icon-size: clamp(2.5rem, 4vw, 3.5rem);
  margin-bottom: 0;
  /* Nudged down onto the heading's optical centre rather than its box top. */
  margin-top: 0.15em;
}

.gp-section__title {
  font-size: clamp(1.0625rem, 0.92rem + 0.7vw, 1.75rem);
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -0.01em;
}

/* Legal prose: readability first. The measure is capped independently of the
   panel so a very wide screen does not produce 200-character lines. */
.gp-section__body > p,
.gp-item p {
  max-width: 78ch;
  font-size: clamp(0.875rem, 0.85rem + 0.32vw, 1.0625rem);
  line-height: 1.65;
  color: var(--color-text-bright);
  text-wrap: pretty;
}

.gp-section__title + p {
  margin-top: 0.5em;
}

.gp-section__body > p + p {
  margin-top: 0.85em;
}

.gp-section__body a {
  color: var(--color-magenta);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  transition: color var(--transition);
}

.gp-section__body a:hover {
  color: var(--color-pink);
}


/* --- 26.6 Policy lists ------------------------------------- */

/* Labelled rows — the reference's icon + bold label + running text. Deliberately
   not cards: section 41 of the brief asks for no unnecessary nested borders, so
   these carry an icon and a hanging indent and nothing else. */
.gp-items {
  display: flex;
  flex-direction: column;
  gap: clamp(0.6rem, 1.2vw, 1rem);
  margin-top: clamp(0.7rem, 1.4vw, 1.1rem);
}

.gp-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(0.6rem, 1.1vw, 0.9rem);
  align-items: start;
}

.gp-item__mark {
  display: grid;
  place-items: center;
  width: clamp(1.25rem, 1.9vw, 1.6rem);
  aspect-ratio: 1;
  margin-top: 0.2em;
  color: var(--color-cyan);
  background-image: linear-gradient(150deg, rgba(56, 189, 248, 0.3) 0%, rgba(34, 211, 238, 0.12) 100%);
  border-radius: 30%;
}

.gp-item__mark svg {
  width: 62%;
  height: 62%;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.gp-item strong {
  color: var(--color-text);
  font-weight: 600;
}

/* Plain bullets, restored deliberately: the global reset removes list markers
   site-wide, and a legal list reads better with a real marker than with a row
   of decorative tiles. The colour ties them to the section icons. */
.gp-bullets {
  max-width: 78ch;
  margin-top: clamp(0.7rem, 1.4vw, 1.1rem);
  padding-left: 1.15em;
  list-style: disc;
}

.gp-bullets li {
  font-size: clamp(0.875rem, 0.85rem + 0.32vw, 1.0625rem);
  line-height: 1.65;
  color: var(--color-text-bright);
  text-wrap: pretty;
}

.gp-bullets li + li {
  margin-top: 0.5em;
}

.gp-bullets li::marker {
  color: var(--color-cyan);
}


/* --- 26.7 Policy contact rows ------------------------------ */

.gp-contact {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(0.6rem, 1.2vw, 1rem);
  margin-top: clamp(0.85rem, 1.7vw, 1.35rem);
}

.gp-contact__item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(0.6rem, 1.1vw, 0.9rem);
  align-items: center;
  padding: clamp(0.7rem, 1.3vw, 1.1rem) clamp(0.8rem, 1.5vw, 1.25rem);
  background-color: var(--color-surface-soft);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.gp-contact__icon {
  --app-icon-size: clamp(1.9rem, 2.9vw, 2.6rem);
  margin-bottom: 0;
}

.gp-contact__body {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.gp-contact__label {
  font-size: clamp(0.8125rem, 0.79rem + 0.26vw, 1rem);
  font-weight: 600;
  line-height: 1.35;
  color: var(--color-text);
}

/* Long addresses must wrap rather than widen the grid track. */
.gp-contact__value {
  font-size: clamp(0.8125rem, 0.79rem + 0.26vw, 1rem);
  line-height: 1.4;
  color: var(--color-magenta);
  overflow-wrap: anywhere;
}

a.gp-contact__value {
  text-decoration: none;
  transition: color var(--transition);
}

a.gp-contact__value:hover {
  color: var(--color-pink);
  text-decoration: underline;
  text-underline-offset: 0.18em;
}


/* --- 26.8 Privacy responsive behaviour --------------------- */

/* The hero flourish is already dropped below 1024px by the About page's rule,
   which is not scoped to that page — the copy needs the hero's full width at
   that size, on any of the pages that use it. */

@media (max-width: 900px) {
  .gp-contact {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 620px) {
  /* The icon tile and the prose would leave the prose about twenty characters
     of width, so the tile moves above the heading and the text takes the row. */
  .gp-section,
  .gp-banner {
    grid-template-columns: minmax(0, 1fr);
  }

  .gp-section__icon,
  .gp-banner__icon {
    margin-top: 0;
  }
}


/* --- 26.9 Print -------------------------------------------- */

/* A legal page should print. Every section is already in the document, so this
   only has to strip the dark theme and the furniture. Scoped to this page so
   the rest of the site is untouched. */
@media print {
  .pixelorbit-privacy-page {
    padding: 0;
    color: #000;
    background: #fff;
  }

  .pixelorbit-privacy-page .site-frame {
    max-width: none;
    padding: 0;
    background: #fff;
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }

  .pixelorbit-privacy-page .sky,
  .pixelorbit-privacy-page .sky__fade,
  .pixelorbit-privacy-page .about-flourish,
  .pixelorbit-privacy-page .nav-toggle,
  .pixelorbit-privacy-page .site-nav,
  .pixelorbit-privacy-page .social,
  .pixelorbit-privacy-page .skip-link,
  .pixelorbit-privacy-page .gp-section__icon,
  .pixelorbit-privacy-page .gp-banner__icon,
  .pixelorbit-privacy-page .gp-contact__icon,
  .pixelorbit-privacy-page .gp-item__mark,
  .pixelorbit-privacy-page .value__icon {
    display: none;
  }

  .pixelorbit-privacy-page .gp-hero {
    min-height: 0;
    padding-inline: 0;
  }

  .pixelorbit-privacy-page .gp-section,
  .pixelorbit-privacy-page .gp-banner,
  .pixelorbit-privacy-page .gp-contact__item,
  .pixelorbit-privacy-page .about-vcard {
    grid-template-columns: minmax(0, 1fr);
    padding-inline: 0;
    background: none;
    border: 0;
  }

  /* Keep a section and its heading together where the engine can manage it. */
  .pixelorbit-privacy-page .gp-section {
    break-inside: avoid;
    padding-block: 0.6rem;
    border-bottom: 1px solid #ccc;
  }

  .pixelorbit-privacy-page h1,
  .pixelorbit-privacy-page h2,
  .pixelorbit-privacy-page h3,
  .pixelorbit-privacy-page p,
  .pixelorbit-privacy-page li,
  .pixelorbit-privacy-page .gp-hero__brand,
  .pixelorbit-privacy-page .gp-banner__title--cyan {
    color: #000;
    -webkit-text-fill-color: #000;
    background: none;
    text-shadow: none;
  }

  .pixelorbit-privacy-page a {
    color: #000;
    text-decoration: underline;
  }

  /* Print the destination of real links, which a sheet of paper cannot follow. */
  .pixelorbit-privacy-page .gp-section__body a[href^="http"]::after,
  .pixelorbit-privacy-page .gp-section__body a[href^="mailto"]::after {
    content: " (" attr(href) ")";
    font-size: 0.85em;
    word-break: break-all;
  }
}


/* =========================================================
   27. Not found (404)
   ---------------------------------------------------------
   Scoped to .page-notfound or to nf- class names used on
   that page alone. The frame, header, footer, buttons and
   .accent-gradient are reused as-is.
   ========================================================= */

/* Shallower than any content hero: there is nothing below this section, so the
   backdrop only has to seat the header and the message rather than carry a
   page's worth of copy down to a panel. */
.page-notfound {
  --sky-height: clamp(30rem, 34vw + 14rem, 62rem);
}

.sky--notfound {
  object-position: center 40%;
}

.sky__fade--notfound {
  background:
    linear-gradient(
      to bottom,
      rgba(5, 7, 15, 0.5) 0%,
      rgba(5, 7, 15, 0.2) 24%,
      rgba(7, 11, 26, 0.34) 58%,
      rgba(7, 11, 26, 0.82) 84%,
      var(--color-bg) 100%
    );
}

/* Centred, unlike every other page on the site. There is no second column and
   no continuing content, so a left-aligned block would sit off-balance in a
   viewport with nothing to its right. */
.nf {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: calc(var(--sky-height) - var(--header-height) - var(--pad-frame));
  padding: clamp(2rem, 4vw, 4rem) var(--pad-x) clamp(3rem, 6vw, 6rem);
  text-align: center;
}

/* Decorative: the heading already says "Page not found", so a screen reader
   that also announced "404" would read the same fact twice. */
.nf__code {
  font-size: clamp(4.5rem, 2rem + 12vw, 12rem);
  font-weight: 700;
  line-height: 0.9;
  letter-spacing: -0.04em;
  color: transparent;
  -webkit-text-stroke: 1.5px rgba(146, 180, 255, 0.34);
  text-stroke: 1.5px rgba(146, 180, 255, 0.34);
}

.nf__title {
  margin-top: clamp(0.75rem, 1.6vw, 1.25rem);
  font-size: clamp(1.9rem, 0.9rem + 4.4vw, 4.25rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.025em;
}

/* Second line of the same heading, so the pair reads as one title. */
.nf__sub {
  display: block;
  font-size: 0.62em;
}

.nf__lead {
  max-width: 36rem;
  margin-top: clamp(0.9rem, 1.8vw, 1.5rem);
  font-size: clamp(0.95rem, 0.9rem + 0.45vw, 1.25rem);
  line-height: 1.7;
  color: var(--color-text-bright);
  text-wrap: pretty;
}

.nf__actions {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(0.75rem, 1.6vw, 1.25rem);
  justify-content: center;
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
}

.nf__links {
  margin-top: clamp(2rem, 4vw, 3.25rem);
}

.nf__links-title {
  font-size: clamp(0.8125rem, 0.78rem + 0.3vw, 1rem);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.nf__list {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(0.5rem, 1.2vw, 1rem) clamp(0.9rem, 2vw, 1.75rem);
  justify-content: center;
  margin-top: clamp(0.7rem, 1.4vw, 1.1rem);
}

.nf__list a {
  font-size: clamp(0.875rem, 0.85rem + 0.32vw, 1.0625rem);
  color: var(--color-text);
  text-decoration: underline;
  text-decoration-color: rgba(125, 165, 255, 0.4);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.28em;
  transition: color var(--transition), text-decoration-color var(--transition);
}

.nf__list a:hover {
  color: var(--color-cyan);
  text-decoration-color: currentColor;
}
