/* ============================================================
   SwiftVisions LLC - Stylesheet
   Color palette derived from the logo: deep black, crimson,
   ember orange, gold, and brushed silver.
   ============================================================ */

:root {
  --bg-deep: #0a0606;
  --bg-base: #100a09;
  --bg-elev: #1a1311;

  --red: #c41e1e;
  --red-bright: #ff3a1f;
  --orange: #ff8a2a;
  --gold: #ffb84d;

  --text: #ececec;
  --text-dim: #b6aeaa;
  --text-mute: #807774;
  --silver: #d9d9d9;

  --grad-fire: linear-gradient(135deg, #ff3a1f 0%, #ff8a2a 55%, #ffb84d 100%);
  --grad-fire-hover: linear-gradient(135deg, #ff553a 0%, #ffa040 55%, #ffc966 100%);
  --grad-silver: linear-gradient(180deg, #ffffff 0%, #b8b0ac 100%);

  --shadow-glow: 0 14px 40px -14px rgba(255, 80, 30, 0.55);

  --nav-height: 72px;
  --maxw: 1200px;
  --radius: 18px;
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 16px;
  line-height: 1.65;
  color: var(--text);
  background-color: var(--bg-deep);
  min-height: 100vh;
  position: relative;
  overflow-x: hidden;
}

/* ---------- Textured background ----------
   Two fixed layers:
   1) Layered radial gradients for an ambient ember glow on a
      near-black canvas.
   2) An SVG fractal-noise overlay (inlined as a data URI) blended
      over the top to give the surface a fine grain.
*/
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -2;
  background:
    radial-gradient(ellipse 80% 60% at 12% 0%,  rgba(255, 100, 40, 0.18), transparent 65%),
    radial-gradient(ellipse 70% 55% at 90% 100%, rgba(196, 30, 30, 0.16), transparent 65%),
    radial-gradient(ellipse 60% 50% at 50% 50%, rgba(40, 16, 12, 0.55), transparent 75%),
    linear-gradient(180deg, #0c0707 0%, #070404 100%);
}
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.55;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='320' height='320'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='matrix' values='0 0 0 0 0.1  0 0 0 0 0.05  0 0 0 0 0.04  0 0 0 0.6 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

/* ---------- Typography ---------- */
h1, h2, h3, h4 {
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 0;
  color: #fff;
}
h1 { font-size: clamp(2.2rem, 5vw, 3.6rem); }
h2 { font-size: clamp(1.8rem, 3.2vw, 2.6rem); }
h3 { font-size: 1.2rem; }
p  { margin: 0 0 1em; }

a {
  color: var(--orange);
  text-decoration: none;
  transition: color 0.2s ease;
}
a:hover { color: var(--gold); }

.container {
  width: min(100% - 2.5rem, var(--maxw));
  margin-inline: auto;
}

.gradient-text {
  background: var(--grad-silver);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.fire-text {
  background: var(--grad-fire);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ---------- Navigation ---------- */
.nav {
  position: sticky;
  top: 0;
  z-index: 100;
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  background: linear-gradient(180deg, rgba(8, 5, 4, 0.88), rgba(8, 5, 4, 0.65));
  border-bottom: 1px solid rgba(255, 138, 42, 0.12);
}
.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--nav-height);
}
.nav__brand {
  display: inline-flex;
  align-items: center;
}
.nav__brand img {
  height: 44px;
  width: auto;
  display: block;
}
.nav__links {
  display: flex;
  gap: 2rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.nav__links a {
  color: var(--silver);
  font-weight: 500;
  font-size: 0.95rem;
  letter-spacing: 0.02em;
  position: relative;
  padding: 0.4rem 0;
}
.nav__links a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -3px;
  width: 100%;
  height: 2px;
  background: var(--grad-fire);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.3s ease;
  border-radius: 1px;
}
.nav__links a:hover,
.nav__links a.is-active { color: #fff; }
.nav__links a:hover::after,
.nav__links a.is-active::after { transform: scaleX(1); }

.nav__toggle {
  display: none;
  background: none;
  border: none;
  color: var(--silver);
  cursor: pointer;
  padding: 0.5rem;
}
.nav__toggle span {
  display: block;
  width: 24px;
  height: 2px;
  background: currentColor;
  margin: 5px 0;
  transition: transform 0.3s ease, opacity 0.3s ease;
  border-radius: 1px;
}

@media (max-width: 760px) {
  .nav__toggle {
    display: block;
    margin-left: auto;
  }
  .nav__links {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: rgba(8, 5, 4, 0.96);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    flex-direction: column;
    padding: 0.75rem 1.25rem 1.25rem;
    gap: 0.25rem;
    border-bottom: 1px solid rgba(255, 138, 42, 0.12);
    transform: translateY(-10px);
    opacity: 0;
    pointer-events: none;
    transition: transform 0.25s ease, opacity 0.25s ease;
  }
  .nav__links.is-open {
    transform: translateY(0);
    opacity: 1;
    pointer-events: auto;
  }
  .nav__links li { width: 100%; }
  .nav__links a { display: block; padding: 0.75rem 0; }
  .nav.is-open .nav__toggle span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .nav.is-open .nav__toggle span:nth-child(2) { opacity: 0; }
  .nav.is-open .nav__toggle span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.85rem 1.75rem;
  border-radius: 999px;
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: 0.02em;
  text-decoration: none;
  cursor: pointer;
  border: 1px solid transparent;
  transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
  white-space: nowrap;
  font-family: inherit;
}
.btn--primary {
  background: var(--grad-fire);
  color: #1a0a05;
  box-shadow: var(--shadow-glow);
}
.btn--primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 18px 50px -14px rgba(255, 80, 30, 0.7);
  background: var(--grad-fire-hover);
  color: #1a0a05;
}
.btn--ghost {
  background: transparent;
  color: var(--silver);
  border-color: rgba(255, 138, 42, 0.4);
}
.btn--ghost:hover {
  border-color: var(--orange);
  color: #fff;
  transform: translateY(-2px);
}

/* ---------- Hero ---------- */
.hero {
  position: relative;
  padding: clamp(3rem, 8vw, 6rem) 0 clamp(3rem, 6vw, 4rem);
  text-align: center;
  overflow: hidden;
}
.hero__glow {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse 60% 45% at 50% 35%, rgba(255, 90, 30, 0.22), transparent 70%);
}
.hero__inner { position: relative; }

.hero__logo {
  position: relative;
  display: inline-block;
  width: min(620px, 92%);
  margin: 0 auto 1.75rem;
  animation: float 6.5s ease-in-out infinite;
}
.hero__title-img {
  display: block;
  width: 100%;
  height: auto;
}
@keyframes float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-8px); }
}

/* ---------- Hero sparkles ----------
   Each sparkle is a 4-point twinkle built from two crossed gradient
   bars (::before vertical, ::after horizontal). The container is
   pinned to the logo bounds and uses `mix-blend-mode: screen` so the
   sparkles read as reflective glints brightening the metal/text
   underneath rather than as separate overlays. */
.hero__sparkles {
  position: absolute;
  inset: 0;
  pointer-events: none;
  mix-blend-mode: screen;
}
.sparkle {
  position: absolute;
  top: var(--top, 50%);
  left: var(--left, 50%);
  width: var(--size, 8px);
  height: var(--size, 8px);
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.3) rotate(0deg);
  animation: twinkle var(--dur, 1.2s) ease-in-out 1 both;
  color: #ffd9a8;
  will-change: opacity, transform;
}
.sparkle::before,
.sparkle::after {
  content: "";
  position: absolute;
}
.sparkle::before {
  left: 50%;
  top: 0;
  bottom: 0;
  width: 2px;
  margin-left: -1px;
  background: linear-gradient(to bottom,
    rgba(255, 230, 190, 0) 0%,
    currentColor 50%,
    rgba(255, 230, 190, 0) 100%);
  border-radius: 2px;
  filter: drop-shadow(0 0 4px currentColor);
}
.sparkle::after {
  top: 50%;
  left: 0;
  right: 0;
  height: 2px;
  margin-top: -1px;
  background: linear-gradient(to right,
    rgba(255, 230, 190, 0) 0%,
    currentColor 50%,
    rgba(255, 230, 190, 0) 100%);
  border-radius: 2px;
  filter: drop-shadow(0 0 4px currentColor);
}
@keyframes twinkle {
  0%, 100% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.25) rotate(0deg);
  }
  50% {
    opacity: 0.9;
    transform: translate(-50%, -50%) scale(1) rotate(45deg);
  }
}

/* Sparkles are spawned continuously by JS (see assets/js/main.js) at random
   positions over the logo's hit regions. Each one lives for a single
   `twinkle` cycle and is then removed. */
.hero__tagline {
  font-size: clamp(1.05rem, 2vw, 1.3rem);
  color: var(--silver);
  max-width: 620px;
  margin: 0 auto 2.25rem;
  line-height: 1.55;
}
.hero__cta {
  display: inline-flex;
  gap: 1rem;
  flex-wrap: wrap;
  justify-content: center;
}

/* Page hero (about / contact) */
.page-hero {
  padding: clamp(2.5rem, 6vw, 4.5rem) 0 clamp(1.5rem, 3vw, 2.5rem);
  text-align: center;
}
.page-hero__eyebrow {
  display: inline-block;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--orange);
  margin-bottom: 0.85rem;
}
.page-hero h1 { margin-bottom: 0.6rem; }
.page-hero p {
  max-width: 620px;
  margin: 0 auto;
  color: var(--text-dim);
  font-size: 1.05rem;
}

/* ---------- Section helpers ---------- */
.section { padding: clamp(3rem, 6vw, 5rem) 0; }
.section__head { text-align: center; margin-bottom: 3rem; }
.section__eyebrow {
  display: inline-block;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--orange);
  margin-bottom: 0.85rem;
}
.section__title { margin-bottom: 0.6rem; }
.section__sub {
  color: var(--text-dim);
  max-width: 640px;
  margin: 0.6rem auto 0;
}

.divider {
  height: 1px;
  width: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 138, 42, 0.35), transparent);
  margin: 0 auto;
  max-width: 360px;
}

/* ---------- App grid ---------- */
.apps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
}
@media (max-width: 920px) { .apps { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .apps { grid-template-columns: 1fr; } }

.app-tile {
  position: relative;
  display: block;
  padding: 1.25rem;
  background:
    linear-gradient(180deg, rgba(40, 24, 22, 0.55), rgba(18, 11, 10, 0.55));
  border: 1px solid rgba(255, 138, 42, 0.16);
  border-radius: var(--radius);
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  transition: transform 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
}
.app-tile::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle 220px at 50% 0%, rgba(255, 138, 42, 0.18), transparent 70%);
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
}
/* Hover effects gated to pointer devices. On iOS Safari, applying
   :hover styles to a link causes the first tap to trigger hover
   instead of navigation, blocking the link from opening until a
   second tap. `@media (hover: hover)` confines these rules to
   real pointer devices so touch taps follow the link immediately. */
@media (hover: hover) {
  .app-tile:hover {
    transform: translateY(-6px);
    border-color: rgba(255, 138, 42, 0.55);
    box-shadow: 0 22px 50px -22px rgba(255, 80, 30, 0.55);
  }
  .app-tile:hover::before { opacity: 1; }
}
.app-tile__img-wrap {
  aspect-ratio: 1 / 1;
  border-radius: 12px;
  overflow: hidden;
  background: rgba(0, 0, 0, 0.4);
  margin-bottom: 1rem;
  position: relative;
}
.app-tile__img-wrap img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.45s ease;
}
@media (hover: hover) {
  .app-tile:hover .app-tile__img-wrap img { transform: scale(1.05); }
}
.app-tile__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
.app-tile__name {
  font-size: 1.05rem;
  font-weight: 600;
  color: #fff;
  letter-spacing: 0.01em;
  margin: 0;
}
.app-tile__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 999px;
  border: 1px solid rgba(255, 138, 42, 0.3);
  color: var(--orange);
  font-size: 0.9rem;
  line-height: 1;
  transition: transform 0.3s ease, background 0.3s ease, color 0.3s ease, border-color 0.3s ease;
}
@media (hover: hover) {
  .app-tile:hover .app-tile__arrow {
    transform: translateX(3px);
    background: var(--grad-fire);
    border-color: transparent;
    color: #1a0a05;
  }
}

/* ---------- Mystery / "coming soon" filler tiles ----------
   Injected by main.js to pad the grid up to a full final row. These
   are non-interactive: a field of faint grey question marks drifts in,
   swells, and fades to hint that something's coming without saying what.
   Greys only, low opacity, so they read as "unknown", not "featured". */
.app-tile--mystery {
  cursor: default;
  border-style: dashed;
  border-color: rgba(255, 255, 255, 0.10);
  background: linear-gradient(180deg, rgba(30, 30, 33, 0.45), rgba(14, 14, 16, 0.45));
}
@media (hover: hover) {
  .app-tile--mystery:hover {
    transform: none;
    border-color: rgba(255, 255, 255, 0.16);
    box-shadow: none;
  }
  .app-tile--mystery:hover::before { opacity: 0; }
}
.app-tile--mystery .app-tile__img-wrap {
  background: rgba(0, 0, 0, 0.3);
}
.app-tile--mystery .app-tile__name { color: rgba(255, 255, 255, 0.42); }
.app-tile--mystery .app-tile__arrow {
  border-color: rgba(255, 255, 255, 0.16);
  color: rgba(255, 255, 255, 0.5);
}

/* Canvas for the drifting question marks; clipped to the square. */
.mystery-field {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}
.mystery-q {
  --rot: 0deg;
  position: absolute;
  top: var(--top);
  left: var(--left);
  font-size: var(--size);
  font-weight: 700;
  line-height: 1;
  color: var(--tone);
  opacity: 0;
  transform: translate(-50%, -50%) rotate(var(--rot)) scale(0.5);
  animation: mysteryQ var(--dur) linear forwards;
  will-change: transform, opacity;
}
@keyframes mysteryQ {
  /* Scale rises linearly with time (0.5 -> 4) so growth is one smooth,
     constant-rate swell; only opacity fades in and back out. Each glyph
     keeps its own fixed random angle (--rot) throughout. */
  0%   { opacity: 0;           transform: translate(-50%, -50%) rotate(var(--rot)) scale(0.5); }
  20%  { opacity: var(--peak); transform: translate(-50%, -50%) rotate(var(--rot)) scale(1.2); }
  65%  { opacity: var(--peak); transform: translate(-50%, -50%) rotate(var(--rot)) scale(2.78); }
  100% { opacity: 0;           transform: translate(-50%, -50%) rotate(var(--rot)) scale(4); }
}
@media (prefers-reduced-motion: reduce) {
  .mystery-q {
    animation: none;
    opacity: var(--peak);
    transform: translate(-50%, -50%) rotate(var(--rot)) scale(1);
  }
}

/* ---------- About / prose ---------- */
.prose {
  max-width: 760px;
  margin: 0 auto;
  font-size: 1.05rem;
  color: var(--text-dim);
}
.prose p { margin: 0 0 1.4em; }
.prose p:first-of-type::first-letter {
  font-size: 3.6rem;
  float: left;
  line-height: 0.95;
  padding: 0.25rem 0.7rem 0 0;
  background: var(--grad-fire);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-weight: 700;
}

.cta-card {
  margin: 4rem auto 0;
  max-width: 760px;
  padding: 2rem;
  text-align: center;
  background: linear-gradient(180deg, rgba(40, 24, 22, 0.6), rgba(18, 11, 10, 0.6));
  border: 1px solid rgba(255, 138, 42, 0.18);
  border-radius: var(--radius);
}

/* Office photo inset between paragraphs of the about page.
   Width is explicitly capped to match the prose column (760px) so
   the figure slots in at the same width as the surrounding text,
   even if a cached older CSS version is still around. */
.office-banner {
  display: block;
  width: 100%;
  max-width: 760px;
  margin: 2.5rem auto;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid rgba(255, 138, 42, 0.18);
  box-shadow:
    0 24px 60px -28px rgba(0, 0, 0, 0.7),
    0 0 0 1px rgba(255, 138, 42, 0.05);
  background: #0a0606;
}
.office-banner img {
  display: block;
  width: 100%;
  height: auto;
}
.cta-card h3 { font-size: 1.4rem; margin-bottom: 0.6rem; }
.cta-card p { color: var(--text-dim); margin-bottom: 1.4rem; }

/* ---------- Contact ---------- */
.contact-grid {
  display: grid;
  grid-template-columns: 1fr 1.1fr;
  gap: 3rem;
  align-items: start;
}
@media (max-width: 820px) {
  .contact-grid { grid-template-columns: 1fr; gap: 2rem; }
}
.contact-info {
  background: linear-gradient(180deg, rgba(40, 24, 22, 0.6), rgba(18, 11, 10, 0.6));
  border: 1px solid rgba(255, 138, 42, 0.16);
  border-radius: var(--radius);
  padding: 2rem;
}
.contact-info h3 {
  font-size: 1.25rem;
  margin-bottom: 0.6rem;
}
.contact-info p { color: var(--text-dim); margin-bottom: 0; }
.contact-info h4 {
  font-size: 0.78rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--orange);
  margin: 1.75rem 0 0.85rem;
}

.social-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  gap: 0.65rem;
  flex-wrap: wrap;
}
.social-list a {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.6rem 1rem;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid rgba(255, 138, 42, 0.22);
  color: var(--silver);
  font-size: 0.9rem;
  transition: transform 0.2s ease, border-color 0.2s ease, color 0.2s ease, background 0.2s ease;
}
.social-list a:hover {
  border-color: var(--orange);
  color: #fff;
  transform: translateY(-2px);
  background: rgba(255, 138, 42, 0.08);
}
.social-list svg {
  width: 18px;
  height: 18px;
  fill: currentColor;
}

/* ---------- Form ---------- */
.form {
  display: grid;
  gap: 1rem;
}
.form__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}
@media (max-width: 520px) { .form__row { grid-template-columns: 1fr; } }
.form__field label {
  display: block;
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 0.4rem;
}
.form input,
.form select,
.form textarea {
  width: 100%;
  padding: 0.85rem 1rem;
  background: rgba(0, 0, 0, 0.4);
  border: 1px solid rgba(255, 138, 42, 0.22);
  border-radius: 12px;
  color: #fff;
  font-family: inherit;
  font-size: 0.95rem;
  transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
}
.form input::placeholder,
.form textarea::placeholder { color: var(--text-mute); }
.form select {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'><path fill='%23ff8a2a' d='M6 8.2L1.4 3.4h9.2z'/></svg>");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  background-size: 12px;
  padding-right: 2.6rem;
}
.form input:focus,
.form select:focus,
.form textarea:focus {
  outline: none;
  border-color: var(--orange);
  background: rgba(0, 0, 0, 0.55);
  box-shadow: 0 0 0 3px rgba(255, 138, 42, 0.18);
}
.form textarea {
  resize: vertical;
  min-height: 150px;
  line-height: 1.55;
}
.form__submit {
  justify-self: start;
  margin-top: 0.5rem;
}
.form__status {
  font-size: 0.9rem;
  color: var(--text-dim);
  min-height: 1.2em;
}
.form__status.is-error { color: #ff7060; }
.form__status.is-success { color: var(--gold); }

/* ---------- Footer ---------- */
.footer {
  border-top: 1px solid rgba(255, 138, 42, 0.12);
  padding: 2.5rem 0;
  margin-top: 4rem;
  text-align: center;
  color: var(--text-mute);
  font-size: 0.9rem;
}
.footer p { margin: 0.25rem 0; }
.footer__updated {
  margin-top: 0.75rem;
  font-size: 0.78rem;
  opacity: 0.6;
}
.footer__brand {
  background: var(--grad-fire);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-weight: 700;
  letter-spacing: 0.02em;
}

/* ---------- Scroll reveal ---------- */
.reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.7s ease, transform 0.7s ease;
}
.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* Stagger app tiles slightly */
.apps .reveal:nth-child(1)  { transition-delay:   0ms; }
.apps .reveal:nth-child(2)  { transition-delay:  60ms; }
.apps .reveal:nth-child(3)  { transition-delay: 120ms; }
.apps .reveal:nth-child(4)  { transition-delay: 180ms; }
.apps .reveal:nth-child(5)  { transition-delay: 240ms; }
.apps .reveal:nth-child(6)  { transition-delay: 300ms; }
.apps .reveal:nth-child(7)  { transition-delay: 360ms; }
.apps .reveal:nth-child(8)  { transition-delay: 420ms; }
.apps .reveal:nth-child(9)  { transition-delay: 480ms; }
.apps .reveal:nth-child(10) { transition-delay: 540ms; }
.apps .reveal:nth-child(11) { transition-delay: 600ms; }
.apps .reveal:nth-child(12) { transition-delay: 660ms; }
.apps .reveal:nth-child(13) { transition-delay: 720ms; }
.apps .reveal:nth-child(14) { transition-delay: 780ms; }
.apps .reveal:nth-child(15) { transition-delay: 840ms; }

/* ---------- Accessibility ---------- */
:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 3px;
  border-radius: 4px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .reveal { opacity: 1; transform: none; }
  .hero__title-img { animation: none; }
}
