/* ============================================================================
   habeat — website. Floating, no-box gallery layout on the near-black canvas.
   Inherits tokens from colors_and_type.css. Dark is the default (and only) theme
   here — the app's launch surface. Paint is the only colour.
   ============================================================================ */

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

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

body {
  margin: 0;
  font-family: var(--font-rounded);
  background: #0C0C0E;
  color: var(--ink-primary);
  --ink-primary:   #F4F2EE;
  --ink-secondary: #A6A6B0;
  --ink-tertiary:  #6D6D75;
  --hair: rgba(255,255,255,.08);
  --hair-strong: rgba(255,255,255,.14);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  line-height: 1.5;
  overflow-x: hidden;
}

/* faint, fixed paint-bloom ambience — one quiet gradient, never loud ------- */
body::before {
  content: "";
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(60% 50% at 78% -6%, rgba(133,56,199,.16), transparent 70%),
    radial-gradient(55% 45% at 8% 4%, rgba(26,148,144,.14), transparent 70%),
    radial-gradient(70% 60% at 50% 116%, rgba(242,56,144,.10), transparent 70%);
}

a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }

/* ---- layout shell -------------------------------------------------------- */
.shell { width: 100%; max-width: 1120px; margin: 0 auto; padding: 0 32px; }
.shell-narrow { max-width: 760px; }

/* ---- type ---------------------------------------------------------------- */
.eyebrow {
  font-size: 12.5px; font-weight: 700; letter-spacing: .22em;
  text-transform: uppercase; color: var(--ink-tertiary); margin: 0;
}
.display {
  font-size: clamp(46px, 8.2vw, 104px); font-weight: 800; line-height: 0.98;
  letter-spacing: -0.035em; margin: 0; text-wrap: balance;
}
.h1 {
  font-size: clamp(34px, 5vw, 60px); font-weight: 800; line-height: 1.02;
  letter-spacing: -0.03em; margin: 0; text-wrap: balance;
}
.h2 {
  font-size: clamp(26px, 3.4vw, 40px); font-weight: 800; line-height: 1.08;
  letter-spacing: -0.025em; margin: 0; text-wrap: balance;
}
.h3 {
  font-size: 22px; font-weight: 700; line-height: 1.2;
  letter-spacing: -0.015em; margin: 0;
}
.lead {
  font-size: clamp(18px, 2vw, 22px); font-weight: 400; line-height: 1.55;
  color: var(--ink-secondary); margin: 0; text-wrap: pretty;
}
.body { font-size: 17.5px; font-weight: 400; line-height: 1.62; color: var(--ink-secondary); margin: 0; text-wrap: pretty; }
.vow { font-style: italic; font-weight: 400; color: var(--ink-secondary); }
.dim { color: var(--ink-tertiary); }
.ink { color: var(--ink-primary); }
.serifnum { font-variant-numeric: tabular-nums; }

/* a paint-washed word — used sparingly on a single keyword */
.paint {
  background: linear-gradient(105deg, #1A9490 0%, #3B82F6 26%, #8538C7 52%, #F23890 74%, #FF6B35 100%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
}

/* ---- nav ----------------------------------------------------------------- */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 50;
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 32px;
  backdrop-filter: blur(14px) saturate(1.2); -webkit-backdrop-filter: blur(14px) saturate(1.2);
  background: linear-gradient(180deg, rgba(12,12,14,.72), rgba(12,12,14,0));
  -webkit-mask-image: linear-gradient(180deg, #000 62%, transparent);
          mask-image: linear-gradient(180deg, #000 62%, transparent);
}
.wordmark { display: inline-flex; align-items: center; gap: 9px; font-weight: 800; font-size: 21px; letter-spacing: -0.02em; }
.wordmark img { width: 26px; height: 26px; filter: drop-shadow(0 2px 8px rgba(242,56,144,.35)); }
.nav-links { display: flex; align-items: center; gap: 30px; position: relative; }
.nav-links a { font-size: 15px; font-weight: 600; color: var(--ink-secondary); white-space: nowrap; transition: color .35s var(--motion-glide), text-shadow .35s var(--motion-glide); position: relative; z-index: 2; }
.nav-links a:hover { color: var(--ink-primary); }
.nav-links .nav-cta { color: var(--ink-primary); }
/* the active link, while a section owns the viewport, lifts to full ink and
   catches a faint breath of its section's hue. */
.nav-links a.is-active { color: var(--ink-primary); text-shadow: 0 0 18px var(--glow-a, transparent); }

/* ---- the travelling nav glow — a soft painted aurora that glides from one
   link to the next as each section arrives, tinted with that section's vibe.
   It lives behind the links (z-index 0) and is positioned/sized in JS. ------- */
.nav-glow {
  position: absolute; top: 50%; left: 0; z-index: 0;
  width: 72px; height: 26px; pointer-events: none;
  transform: translate(-50%, -50%) scaleX(1);
  opacity: 0; will-change: transform, width, opacity;
  --glow-a: #6FC4BB; --glow-b: #3B8B85;
}
/* the bloom — a soft, diffuse wash of light behind the link. Heavily blurred
   and edge-faded so it reads as ambient glow, never a solid pill. */
.nav-glow .glow-bloom {
  position: absolute; inset: -85% -22%;
  border-radius: 999px;
  background: linear-gradient(115deg, var(--glow-a), var(--glow-b));
  filter: blur(17px) saturate(1.05);
  opacity: .42;
  -webkit-mask: radial-gradient(ellipse 60% 52% at 50% 50%, #000 8%, transparent 70%);
          mask: radial-gradient(ellipse 60% 52% at 50% 50%, #000 8%, transparent 70%);
  animation: navBreath 6.4s ease-in-out infinite;
}
@keyframes navBreath {
  0%, 100% { transform: scale(1);    opacity: .4;  }
  50%      { transform: scale(1.06); opacity: .56; }
}
@media (prefers-reduced-motion: reduce) {
  .nav-glow .glow-bloom { animation: none; }
}

/* ---- calm CTA button (the one allowed "object") -------------------------- */
.btn {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: inherit; font-size: 16px; font-weight: 700; letter-spacing: -0.01em;
  padding: 14px 26px; border-radius: 999px; cursor: pointer;
  border: 1px solid rgba(255,255,255,.14);
  color: var(--ink-primary); background: rgba(255,255,255,.05);
  transition: transform .18s var(--motion-tap), background .25s ease, border-color .25s ease;
}
.btn:hover { background: rgba(255,255,255,.10); border-color: rgba(255,255,255,.24); transform: translateY(-1px); }
.btn-quiet { border: 0; background: none; padding: 14px 4px; color: var(--ink-secondary); }
.btn-quiet:hover { color: var(--ink-primary); background: none; transform: none; }
.btn .dot { width: 7px; height: 7px; border-radius: 999px; background: var(--status-success); box-shadow: 0 0 12px var(--status-success); }

/* ---- hairline rule ------------------------------------------------------- */
.rule { height: 1px; border: 0; margin: 0; background: var(--hair); }

/* ---- floating illustration ----------------------------------------------- */
.float { position: relative; }
.float img { position: relative; z-index: 1; }
/* the travelling breath-orb now supplies the glow behind each icon, so the old
   static paint-puddle is retired (kept as a no-op for any stray .float). */
.float::after { content: none; }

/* ---- section rhythm ------------------------------------------------------ */
/* Sections sit ABOVE the fixed travel-orb (z-index:0) so content stays legible;
   their faint hue-wash backgrounds let the orb glow through and, drifting from
   one accent to the next, demarcate sections WITHOUT any hairlines. */
header.sec, section, .foot { position: relative; z-index: 1; }
.sec { padding: clamp(80px, 12vh, 150px) 0; }
.sec-tight { padding: clamp(56px, 8vh, 100px) 0; }

/* soft hue-shift bands — each section drifts to the next's top hue, so the seams
   dissolve while the mid-tones stay distinct (the demarcation, in colour) */
.band-a { background: linear-gradient(180deg, rgba(26,148,144,0),   rgba(133,56,199,.060)); }
.band-b { background: linear-gradient(180deg, rgba(133,56,199,.052), rgba(242,56,144,.052)); }
.band-c { background: linear-gradient(180deg, rgba(242,56,144,.046), rgba(26,148,144,.052)); }
.band-d { background: linear-gradient(180deg, rgba(26,148,144,.052), rgba(59,130,246,.046)); }
.band-e { background: linear-gradient(180deg, rgba(59,130,246,.046), rgba(133,56,199,.062)); }
.band-f { background: linear-gradient(180deg, rgba(133,56,199,.052), rgba(12,12,14,0)); }

/* feature row: text + floating illustration, alternating, no boxes */
.feature { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(32px, 6vw, 96px); align-items: center; }
.feature.flip .feature-art { order: -1; }
.feature-art { display: grid; place-items: center; }
.feature-art img { width: min(360px, 78%); }
.stack-sm > * + * { margin-top: 14px; }
.stack-md > * + * { margin-top: 22px; }
.stack-lg > * + * { margin-top: 40px; }

/* ---- vibe progression TILES (the colour you earn) -----------------------
   The app renders streak depth as rounded-square heatmap tiles, not circles —
   so the website speaks the same language. Each tile is one intensity stop of
   the Sunrise family, deepening early → deep bloom. */
.vibes { display: flex; gap: clamp(16px, 4vw, 44px); flex-wrap: wrap; }
.vibe-step { display: flex; flex-direction: column; align-items: center; gap: 14px; }
.vibe-orb { width: clamp(74px, 12vw, 116px); aspect-ratio: 1; border-radius: 22px;
  box-shadow: 0 16px 40px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.16);
  position: relative; overflow: hidden; }
/* a glossy paint sheen across every tile, like the app's painted surface */
.vibe-orb::before { content:""; position:absolute; inset:0; border-radius:inherit;
  background: radial-gradient(72% 60% at 28% 22%, rgba(255,255,255,.30), transparent 62%);
  mix-blend-mode: plus-lighter; }
.vibe-orb.s1 { background: linear-gradient(135deg,#FFD7A6,#FFB37A); }
.vibe-orb.s2 { background: linear-gradient(135deg,#FF9E63,#E07650); }
.vibe-orb.s3 { background: linear-gradient(135deg,#C9522D,#6E1F12); }
.vibe-orb.s4 { background: linear-gradient(135deg,#A83A1F,#4A1208); }
.vibe-orb.s4::after { content:""; position:absolute; inset:0; border-radius:inherit;
  background: radial-gradient(60% 60% at 70% 74%, rgba(255,150,90,.40), transparent 58%); mix-blend-mode: plus-lighter; }
.vibe-step .lbl { font-size: 14px; font-weight: 700; color: var(--ink-primary); }
.vibe-step .sub { font-size: 12.5px; color: var(--ink-tertiary); }

/* ---- pricing: typographic tiers. No lines, no boxes, no static glow — the
   travelling orb splits into three and crowns each price as you arrive. ------ */
.tiers { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(12px,2.4vw,30px); }
.tier { position: relative; padding: 30px clamp(18px,3vw,38px); text-align: center; }
.tier .price { font-size: clamp(34px,4.4vw,52px); font-weight: 800; letter-spacing: -0.03em; line-height: 1; font-variant-numeric: tabular-nums; }
.tier .per { font-size: 16px; font-weight: 600; color: var(--ink-tertiary); }
.tier .tname { font-size: 13px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-secondary); }
.tier .tdesc { font-size: 15.5px; color: var(--ink-secondary); line-height: 1.5; margin-left:auto; margin-right:auto; max-width: 26ch; }

/* ---- legal / reading column --------------------------------------------- */
.legal { padding-top: 132px; padding-bottom: 120px; }
.legal h1.display { font-size: clamp(40px, 6vw, 72px); }
.legal .meta { font-size: 14px; color: var(--ink-tertiary); margin-top: 18px; }
.legal h2 { font-size: 24px; font-weight: 800; letter-spacing: -0.02em; margin: 0 0 4px; color: var(--ink-primary); }
.legal h3 { font-size: 17.5px; font-weight: 700; margin: 0 0 4px; color: var(--ink-primary); }
.legal p, .legal li { font-size: 17px; line-height: 1.68; color: var(--ink-secondary); text-wrap: pretty; }
.legal p { margin: 0 0 14px; }
.legal section { margin-top: 52px; }
.legal section > .eyebrow { margin-bottom: 18px; }
.legal ul { margin: 0 0 14px; padding-left: 22px; }
.legal li { margin-bottom: 9px; }
.legal li::marker { color: var(--ink-tertiary); }
.legal a.link { color: var(--ink-primary); border-bottom: 1px solid var(--hair-strong); padding-bottom: 1px; transition: border-color .2s; }
.legal a.link:hover { border-color: var(--ink-primary); }
.legal strong { color: var(--ink-primary); font-weight: 700; }
.toc { font-size: 15px; }
.toc a { display: block; padding: 7px 0; color: var(--ink-secondary); border-bottom: 1px solid var(--hair); transition: color .2s, padding-left .2s; }
.toc a:hover { color: var(--ink-primary); padding-left: 6px; }

/* ---- footer -------------------------------------------------------------- */
.foot { padding: 60px 0 70px; }
.foot-grid { display: flex; align-items: flex-start; justify-content: space-between; gap: 40px; flex-wrap: wrap; }
.foot-links { display: flex; gap: 30px; flex-wrap: wrap; }
.foot-links a { font-size: 15px; color: var(--ink-secondary); transition: color .2s; }
.foot-links a:hover { color: var(--ink-primary); }
.foot-fine { font-size: 13px; color: var(--ink-tertiary); margin-top: 26px; line-height: 1.6; }

/* ---- entrance: quiet rise --------------------------------------------------
   Content is ALWAYS visible. The animation is decoration only: .is-in (added by
   JS when an element scrolls into view) plays a one-shot rise. If JS never runs,
   if IntersectionObserver is missing, or under reduced-motion, content simply
   shows — it can never be left hidden. */
.rise { opacity: 1; transform: none; }

@media (prefers-reduced-motion: no-preference) {
  .rise.is-in { animation: riseIn .7s var(--motion-glide) both; }
  .rise.is-in.d1 { animation-delay: .07s; }
  .rise.is-in.d2 { animation-delay: .14s; }
  .rise.is-in.d3 { animation-delay: .21s; }
  .rise.is-in.d4 { animation-delay: .28s; }
}
@keyframes riseIn {
  from { transform: translateY(18px); }
  to   { transform: none; }
}

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

/* ---- the travelling breath-orb ------------------------------------------
   The app's check-off orb / BreathingGradient sphere, lifted onto the web: a
   glossy gradient sphere with the painted icon resting on its face. One orb
   travels between icons as you scroll — centred on whichever icon is nearest
   view-centre, shrinking through each seam, then blooming back on the next icon
   in a fresh theme hue. Sits BEHIND content (z-index:0); icons (z-index:1) rest
   on top. JS sets size + position + hue. Decorative — hidden to reduced-motion.
   The breath rides a CSS variable so it composes with the JS travel transform. */
.travel-orb {
  position: fixed; top: 0; left: 0; z-index: 0; pointer-events: none;
  width: 360px; height: 360px; opacity: 0;
  mix-blend-mode: screen; will-change: transform, opacity, width, height;
  filter: blur(2px);
}
.orb-glow { display: none; }
.orb-core { /* the original soft, diffuse paint-glow nebula (screen-blended) */
  position: absolute; inset: 0; border-radius: 50%;
  background:
    radial-gradient(58% 58% at 32% 28%, var(--orb-hi, #A8D8B8), transparent 70%),
    radial-gradient(62% 62% at 74% 76%, var(--orb-b, #3D6F52), transparent 72%),
    radial-gradient(46% 46% at 70% 24%, rgba(242,56,144,.55), transparent 66%),
    radial-gradient(50% 50% at 24% 74%, rgba(133,56,199,.55), transparent 70%),
    radial-gradient(closest-side, var(--orb-a, #6FB286), transparent 78%);
  filter: blur(14px);
  transition: background .9s ease;
}
.orb-core::after { /* a tighter, brighter inner bloom for body */
  content: ""; position: absolute; inset: 14%; border-radius: 50%;
  background: radial-gradient(closest-side, var(--orb-hi, #A8D8B8), transparent 76%);
  opacity: .55; filter: blur(10px);
}
@media (prefers-reduced-motion: no-preference) {
  .orb-core { animation: orbBreathe 6.4s ease-in-out infinite; }
}
@keyframes orbBreathe {
  0%, 100% { transform: scale(1);    opacity: .92; }
  50%      { transform: scale(1.06); opacity: 1;   }
}
@media (prefers-reduced-motion: reduce) {
  .travel-orb { display: none; }
}

/* ---- responsive ---------------------------------------------------------- */
@media (max-width: 860px) {
  .shell { padding: 0 22px; }
  .feature { grid-template-columns: 1fr; gap: 36px; }
  .feature.flip .feature-art { order: 0; }
  .feature-art img { width: min(300px, 64%); }
  .nav-links { gap: 18px; }
  .nav-links a:not(.nav-cta) { display: none; }
  .tiers { grid-template-columns: 1fr; }
  .tier { padding: 30px 0; }
}
@media (max-width: 520px) {
  .nav { padding: 14px 20px; }
  .vibes { gap: 18px; justify-content: space-between; }
}

/* ============================================================================
   HERO — TAP TO REVEAL  (v3)
   At load (html.js-anim, not yet .held) scrolling is locked and the hero shows
   ONLY the dormant grey mark + its empty streak ring, centred in the viewport
   by JS. ONE TAP fills the ring, blooms the mark from grey into colour with a
   soft chord, then the mark glides into the orb slot of the app's real painted
   lead card (PaintedSurface) whose body is the hero message; scrolling unlocks.
   Full colour + full layout + free scroll is the no-JS / reduced-motion default,
   so nothing is ever hidden or trapped. Interpolation rides --reveal (0 → 1).
   ============================================================================ */
.hero { min-height: 100vh; display: flex; align-items: center; }

/* lock scrolling during the dormant opening (JS-applied; never under no-JS) */
html.scroll-lock, html.scroll-lock body { overflow: hidden; height: 100%; }

/* the wrapper: orb + mark on the LEFT (the brand's living paint-nebula), the
   dominant message card on the RIGHT — side by side, never overlapping. */
.hero-card-wrap {
  position: relative; max-width: 1080px; margin: 0 auto;
  display: grid; grid-template-columns: minmax(248px, 340px) 1fr;
  align-items: center; gap: clamp(28px, 4.5vw, 64px);
}

/* ---- the hero's lead card == the app's painterly Home main card the way it
   reads when the day is held: ONE living theme gradient (set by JS, deepening
   as you keep holding) + the brand-accent swirl + a deep bloom + breathing
   sheen. One gradient alive — not the old multi-hue gallery soup. --------- */
.appcard {
  position: relative; border-radius: 24px; overflow: hidden;
  padding: clamp(34px, 4vw, 54px); min-height: 360px;
  display: flex; align-items: center;
  background: linear-gradient(135deg, var(--card-a, #3B8B85), var(--card-b, #266D65));
  border: 1px solid rgba(255,255,255,.08);
  box-shadow: 0 1px 2px rgba(0,0,0,.4), 0 22px 54px rgba(0,0,0,.5);
}
/* the brand-accent swirl (PaintedSurface): teal / violet / pink washes,
   plus-lighter, drifting slowly — the mark's multi-hue energy, restrained */
.appcard::before {
  content: ""; position: absolute; inset: 0; opacity: .32; mix-blend-mode: plus-lighter;
  background:
    radial-gradient(60% 70% at 16% 28%, var(--accent-teal), transparent 70%),
    radial-gradient(55% 60% at 86% 74%, var(--accent-violet), transparent 70%),
    radial-gradient(50% 55% at 72% 16%, var(--accent-pink), transparent 70%);
}
@media (prefers-reduced-motion: no-preference) {
  .appcard::before { animation: paintDrift 15s ease-in-out infinite; }
}
@keyframes paintDrift {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50%      { transform: translate(2%, -1.6%) scale(1.05); }
}
/* deep bloom rising from the base (the theme's deep stop, set by JS) + a top
   sheen + a soft vignette scrim so the cream copy always reads over the paint */
.appcard::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(120% 90% at 50% 122%, var(--card-bloom, #134D48), transparent 60%),
    linear-gradient(180deg, rgba(255,255,255,.07), transparent 34%),
    radial-gradient(130% 120% at 55% 46%, transparent 50%, rgba(8,12,12,.46) 100%);
}
.appcard-fx { position: absolute; inset: 0; pointer-events: none; }   /* breathing veil */
@media (prefers-reduced-motion: no-preference) {
  .appcard-fx {
    background: radial-gradient(140% 110% at 20% 18%, rgba(255,255,255,.05), transparent 55%);
    mix-blend-mode: plus-lighter; animation: cardBreathe 4.8s ease-in-out infinite;
  }
}
@keyframes cardBreathe { 0%,100% { opacity:.4; } 50% { opacity:.85; } }

.appcard-body { position: relative; z-index: 1; color: #FAF8F5; width: 100%; }
.appcard-eyebrow { color: rgba(244,242,238,.66); margin-bottom: 14px; }
.appcard-title {
  font-size: clamp(30px, 3.7vw, 46px); font-weight: 800; line-height: 1.03;
  letter-spacing: -0.03em; margin: 0; text-wrap: balance;
  text-shadow: 0 2px 24px rgba(0,0,0,.45);
}
.appcard-lead {
  font-size: clamp(16.5px, 1.7vw, 19px); line-height: 1.55; margin: 16px 0 0;
  color: rgba(244,242,238,.92); max-width: 40ch; text-wrap: pretty;
  text-shadow: 0 1px 12px rgba(0,0,0,.4);
}
.appcard-cta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 24px; }
.appcard-cta .btn { white-space: nowrap; }
.btn-on-paint { background: #FAF8F5; color: #15241B; border-color: transparent; }
.btn-on-paint:hover { background: #fff; border-color: transparent; transform: translateY(-1px); }
.btn-quiet-paint { color: rgba(244,242,238,.82); }
.btn-quiet-paint:hover { color: #FAF8F5; }

/* ---- the painted mark over the ONE travelling paint-orb -------------------
   The hero mark is just another [data-orb-icon]: the site's single travelling
   orb (orb 0, the fixed .travel-orb) parks behind it and glows through, exactly
   as it does behind every icon down the page — then journeys on as you scroll.
   At load it's dim + grey (via the :not(.held) travel-orb filter); one tap wakes
   its colour. The thin streak ring is the tap affordance and dissolves after. */
.hold-group {
  position: relative; z-index: 5; justify-self: center;
  display: grid; place-items: center;
  opacity: 1; transition: transform 1.05s var(--motion-glide), opacity .5s ease;
  will-change: transform, opacity;
}
.hold-stage {
  position: relative; display: grid; place-items: center;
  width: 260px; max-width: 78vw;
  cursor: pointer; -webkit-tap-highlight-color: transparent; touch-action: manipulation; outline: none;
}
.hold-stage > * { grid-area: 1 / 1; }

.hold-mark { width: 100%; }

/* the painted mark, two stacked layers + a wet leading edge.
   --bleed (0→1) raises a feathered diagonal mask up the COLOUR layer, so the
   paint floods up through the glyph along its swirl; the stone layer sits
   beneath as the dormant, unearned letter. --depth (0→1) richens the woken
   paint as the streak deepens. Parallax + glide ride the container. */
.mark-paint {
  display: grid; place-items: center; width: 164px; margin: 0 auto;
  transform: translate3d(var(--mx, 0px), var(--my, 0px), 0);
  transition: transform .35s var(--motion-glide);
}
.mark-paint > * { grid-area: 1 / 1; width: 164px; display: block; }
.mark-stone {
  filter: grayscale(1) brightness(.58) contrast(1.06)
          drop-shadow(0 12px 26px rgba(0,0,0,.55));
}
.mark-colour {
  --edge: calc(var(--bleed, 0) * 132% - 16%);
  -webkit-mask-image: linear-gradient(to top right, #000 0%, #000 var(--edge), transparent calc(var(--edge) + 16%), transparent 100%);
          mask-image: linear-gradient(to top right, #000 0%, #000 var(--edge), transparent calc(var(--edge) + 16%), transparent 100%);
  filter:
    saturate(calc(1.08 + .4 * var(--depth, 0)))
    brightness(calc(1.08 - .16 * var(--depth, 0)))
    contrast(calc(1.02 + .07 * var(--depth, 0)))
    drop-shadow(0 14px 30px rgba(0,0,0,.5));
}
/* a thin luminous line riding the leading edge of the rising paint (wet gloss),
   clipped to the glyph silhouette so the sheen stays *inside* the letter.
   Brightest mid-rise, invisible at rest and when full. */
.mark-wet {
  --edge: calc(var(--bleed, 0) * 132% - 16%);
  pointer-events: none; mix-blend-mode: plus-lighter;
  opacity: calc(2.6 * var(--bleed, 0) * (1 - var(--bleed, 0)));
  background: linear-gradient(to top right,
    transparent calc(var(--edge) - 5%), rgba(255,249,242,.85) calc(var(--edge) + 1%),
    rgba(255,243,232,.35) calc(var(--edge) + 5%), transparent calc(var(--edge) + 11%));
  -webkit-mask-image: url("assets/mark-h.png");
  -webkit-mask-size: 164px 164px; -webkit-mask-repeat: no-repeat; -webkit-mask-position: center;
          mask-image: url("assets/mark-h.png");
          mask-size: 164px 164px; mask-repeat: no-repeat; mask-position: center;
}

/* the thin streak ring — the tap affordance; rims the orb, fills as colour wakes,
   then dissolves once tapped (every other orb on the site has no ring). */
.hold-ring {
  width: 248px; max-width: 78vw; aspect-ratio: 1; transform: rotate(-90deg);
  pointer-events: none; opacity: 0;
  transition: opacity .6s ease, transform .8s var(--motion-glide);
}
.hold-ring circle { fill: none; stroke-width: 0.9; }
.hold-ring-track { stroke: rgba(255,255,255,.12); }
.hold-ring-fill {
  stroke: url(#holdGrad); stroke-linecap: round;
  stroke-dasharray: 289; stroke-dashoffset: 289;
  filter: drop-shadow(0 0 6px rgba(242,56,144,.5));
}

.hold-pulse {
  width: 248px; max-width: 78vw; aspect-ratio: 1; border-radius: 50%;
  pointer-events: none; opacity: 0; will-change: transform, opacity; justify-self: center;
  background: radial-gradient(closest-side,
    transparent 48%, rgba(133,56,199,.32) 70%, rgba(242,56,144,.16) 86%, transparent 100%);
}
.hold-pulse.go { animation: holdPulse 1.05s var(--motion-settle) forwards; }
@keyframes holdPulse {
  0%   { opacity: .85; transform: scale(.72); }
  100% { opacity: 0;  transform: scale(1.7); }
}

/* the invitation */
.hold-hint {
  position: absolute; top: calc(100% + 16px); left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; justify-content: center; gap: 10px;
  margin: 0; font-size: 13px; font-weight: 700; letter-spacing: .18em; white-space: nowrap;
  text-transform: uppercase; color: var(--ink-tertiary);
  opacity: 0; transition: opacity .55s ease, color .5s ease;
}
.hold-hint .hh-ring {
  width: 9px; height: 9px; border-radius: 50%; border: 2px solid currentColor;
  opacity: .7; animation: hintPulse 2.6s ease-in-out infinite;
}
@keyframes hintPulse {
  0%, 100% { transform: scale(1);    opacity: .45; }
  50%      { transform: scale(1.28); opacity: .95; }
}
.hold-hint.is-held { color: var(--ink-secondary); letter-spacing: .12em; }
.hold-hint.is-held .hh-ring {
  border: 0; background: var(--status-success);
  box-shadow: 0 0 12px var(--status-success); animation: none; opacity: 1;
}

/* The dormant "hold to wake" opening belonged to the old single-page hero
   (index.legacy.html, removed 2026-07-26). Its state rules are gone: nothing
   in support/privacy/terms has a .held class, so `html.js-anim:not(.held) .nav`
   was pinning the nav at opacity 0 on all three pages — an invisible,
   unclickable header. Only the plain transitions survive. */
.appcard { transition: opacity .85s var(--motion-glide), transform .85s var(--motion-glide); }
.nav { transition: opacity .7s ease, transform .7s ease, color .35s var(--motion-glide), text-shadow .35s var(--motion-glide), background .25s ease, border-color .25s ease; }

.hold-stage:focus-visible .hold-ring-track { stroke: rgba(255,255,255,.26); }

/* ---- hero responsive: stack the orb above the card on narrow screens ----- */
@media (max-width: 820px) {
  .hero-card-wrap { grid-template-columns: 1fr; justify-items: center; gap: clamp(20px, 5vw, 40px); }
  .appcard { min-height: 0; width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .hold-ring, .hold-hint { display: none; }
}
