/* ═══════════════════════════════════════════════════════════════════════════
   ios.css — the iOS layer, loaded after styles.css.

   styles.css is the apple.com grammar (type, rails, sections). This file is
   the part that makes the page read as iOS itself: her Home Screen, app
   icons, widgets, the App Store sheet, the contact poster, and the Apple
   Intelligence glow that ties them together.

   · Everything inside a phone is sized in cqi (1% of the screen width), so
     the whole Home Screen scales as one object with a single knob, --dw.
   · The glow is the Apple Intelligence palette on a conic gradient. It is
     rotated with the `rotate` property only (compositor, no repaint) and
     paused whenever its phone is off screen.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── TOKENS ────────────────────────────────────────────────────────────── */
:root {
  --ai-blue:   #0a84ff;
  --ai-cyan:   #64d2ff;
  --ai-indigo: #5e5ce6;
  --ai-purple: #bf5af2;
  --ai-pink:   #ff375f;
  --ai-orange: #ff9f0a;
  --ai-conic: conic-gradient(from 0deg,
      var(--ai-blue), var(--ai-indigo) 14%, var(--ai-purple) 30%, var(--ai-pink) 46%,
      var(--ai-orange) 58%, var(--ai-pink) 70%, var(--ai-purple) 82%, var(--ai-cyan) 92%, var(--ai-blue));
  /* Gradient ink for text on light grounds: deepened so every stop holds
     at least 3:1 on white at display sizes. */
  --ai-ink: linear-gradient(90deg, #0071e3 0%, #7d3cf0 36%, #d6307a 70%, #e0660a 100%);

  --btn-blue:        #0071e3;
  --btn-blue-hover:  #0077ed;
  --btn-blue-active: #006edb;

  --halo-o: .42;
  --phone-shadow:
    0 2px 6px rgba(0, 0, 0, .08),
    0 30px 60px -24px rgba(0, 0, 0, .42);
  --spring: cubic-bezier(.2, .9, .25, 1);
}

.sprite { position: absolute; width: 0; height: 0; overflow: hidden }

/* ── APPLE INTELLIGENCE INK ───────────────────────────────────────────── */
.ai-text {
  background: var(--ai-ink);
  -webkit-background-clip: text; background-clip: text;
  color: transparent; -webkit-text-fill-color: transparent;
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
.stat .t-stat.ai-text { color: transparent }
@media (forced-colors: active) {
  .ai-text { background: none; color: CanvasText; -webkit-text-fill-color: CanvasText }
}

/* ── BUTTONS · Apple blue ─────────────────────────────────────────────── */
.button--primary         { background: var(--btn-blue); color: #fff }
.button--primary:hover   { background: var(--btn-blue-hover); color: #fff }
.button--primary:active  { background: var(--btn-blue-active); color: #fff }
.button--secondary       { color: var(--link); border-color: currentColor }
.button--secondary:hover { background: var(--btn-blue-hover); color: #fff; border-color: transparent }
.button--secondary:active{ background: var(--btn-blue-active); color: #fff; border-color: transparent }

/* ── AWARD BADGE · modern gold between App Store laurels ──────────────────
   The one colour outside the Apple Intelligence palette, on purpose. Flat
   champagne pill, metallic hairline, gold-gradient ink (every stop ≥ 4.6:1
   on the fill, AA at 12px), flanked by the laurels the App Store puts round
   its own awards. When the featured case comes into view, a light sweep
   crosses it while the confetti falls (JS adds .is-celebrating). */
.badge {
  position: relative; overflow: hidden; isolation: isolate;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 12px; border: 1px solid transparent; border-radius: var(--r-pill);
  background:
    linear-gradient(180deg, #fffcf3 0%, #fbf0d2 100%) padding-box,
    linear-gradient(120deg, #e2c27a 0%, #b88a2c 30%, #f3dc98 52%, #b0801f 76%, #e6c983 100%) border-box;
  color: #7a5600;
  font-weight: 600;
}
.badge__text {
  background: linear-gradient(100deg, #6b4700 0%, #936605 40%, #6e4a00 65%, #5a3c00 100%);
  -webkit-background-clip: text; background-clip: text;
  color: transparent; -webkit-text-fill-color: transparent;
}
.laurel { flex: none; width: 10px; height: 18px; color: #b0831f }
.laurel--end { transform: scaleX(-1) }
.badge::after {
  content: ""; position: absolute; inset: -1px; z-index: 1; pointer-events: none;
  background: linear-gradient(105deg, transparent 32%, rgba(255, 255, 255, .9) 47%, transparent 62%);
  transform: translateX(-130%);
}
.badge.is-celebrating::after { animation: badgeShine 1.25s cubic-bezier(.4, 0, .2, 1) .2s 3 }
@keyframes badgeShine { to { transform: translateX(130%) } }
@media (forced-colors: active) {
  .badge { background: Canvas; border-color: CanvasText }
  .badge__text { background: none; color: CanvasText; -webkit-text-fill-color: CanvasText }
}

/* Confetti: one canvas, made by JS for the celebration, then removed. */
.confetti { position: fixed; inset: 0; z-index: 95; width: 100%; height: 100%; pointer-events: none }

/* ═══ THE PHONE ═════════════════════════════════════════════════════════════
   iPhone 17 proportions: body 71.5 × 149.6 mm, bezel 2.45 mm.
   screen_radius = device_radius − bezel, all from --dw.                   */
.phone-wrap { position: relative; width: fit-content; max-width: 100%; margin-inline: auto; isolation: isolate }

.phone {
  --dw: 400px;
  --lip:   calc(var(--dw) * .0085);
  --bezel: calc(var(--dw) * .0343);
  --r-dev: calc(var(--dw) * .178);
  --r-scr: calc(var(--r-dev) - var(--bezel));
  position: relative; z-index: 1; box-sizing: border-box;
  width: var(--dw); aspect-ratio: 71.5 / 149.6;
  border: var(--lip) solid transparent;
  padding: calc(var(--bezel) - var(--lip));
  border-radius: var(--r-dev);
  background:
    linear-gradient(#050506, #050506) padding-box,
    linear-gradient(148deg, #9a9aa0 0%, #3a3a3d 10%, #1c1c1e 34%, #2c2c2e 52%,
                            #86868b 78%, #2c2c2e 92%, #4a4a4d 100%) border-box;
  box-shadow: var(--phone-shadow);
  /* The query container is the PHONE, not the screen: an element's own cqi
     resolve against its ancestor container, so the screen's cqi padding
     needs one above it. The phone's content box is exactly the screen. */
  container-type: inline-size;
}
@media (max-width: 1068px) { .phone { --dw: 380px } }
@media (max-width:  734px) { .phone { --dw: min(340px, 86vw) } }

.phone__screen {
  position: relative; height: 100%; overflow: hidden;
  border-radius: var(--r-scr);
  background: #000; color: #fff;
  isolation: isolate;                 /* NOT a container: see .phone */
  font-family: var(--font-text);
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
  -webkit-tap-highlight-color: transparent;
}

/* Status bar — this phone draws its own UI, so here the island is ours. */
.sbar {
  position: absolute; inset: 0 0 auto; z-index: 4; height: 14cqi;
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 7cqi 0 10cqi; pointer-events: none; color: #fff;
}
.sbar__time { width: 16cqi; text-align: center; margin-top: .8cqi;
              font: 600 4.3cqi/1 var(--font-text); letter-spacing: -.01em }
.sbar__island {
  position: absolute; left: 50%; top: 2.9cqi; transform: translateX(-50%);
  width: 31cqi; height: 9.2cqi; border-radius: 9cqi; background: #000;
}
.sbar__icons { display: flex; align-items: center; gap: 1.5cqi; margin-top: .8cqi }
.sbar__icons svg { fill: currentColor }
.sb-signal  { width: 4.6cqi; height: 3.05cqi }
.sb-wifi    { width: 4.2cqi; height: 3.15cqi }
.sb-battery { width: 6.6cqi; height: 3.2cqi }

.phone__indicator {
  position: absolute; z-index: 5; left: 50%; bottom: 2.2cqi; transform: translateX(-50%);
  width: 34cqi; height: 1.35cqi; border-radius: 1cqi; background: rgba(255, 255, 255, .88);
  pointer-events: none;
}

/* ═══ HOME SCREEN ═══════════════════════════════════════════════════════════
   4 columns of 15.5cqi icons across 87cqi: the gutter is 8.33cqi, and a
   small widget is exactly two icons plus one gutter, as on iOS.           */
.home {
  display: flex; flex-direction: column;
  padding: 15.5cqi 6.5cqi 5.4cqi;
}
.home::before {                     /* the wallpaper, on its own layer so it can zoom */
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    radial-gradient(90% 50% at 10% 4%,  rgba(94, 92, 230, .9),  transparent 64%),
    radial-gradient(80% 46% at 100% 30%, rgba(191, 90, 242, .7), transparent 62%),
    radial-gradient(95% 50% at 88% 100%, rgba(255, 55, 95, .72), transparent 64%),
    radial-gradient(80% 44% at 0% 78%,  rgba(255, 159, 10, .5),  transparent 62%),
    linear-gradient(180deg, #17153b 0%, #24123a 52%, #331226 100%);
  transition: transform 1.1s var(--spring);
}

.hs-label {
  display: block; max-width: 22cqi; margin-top: 1.3cqi;
  font: 400 3cqi/3.7cqi var(--font-text); letter-spacing: 0; color: #fff;
  text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  text-shadow: 0 .2cqi .9cqi rgba(0, 0, 0, .35);
}

.home__widgets { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 8.33cqi }
.hs-slot { display: flex; flex-direction: column; align-items: center; min-width: 0 }
.hs-slot > .hs-label { max-width: 100% }

.widget {
  position: relative; display: flex; flex-direction: column; width: 100%; aspect-ratio: 1;
  border-radius: 5.6cqi; overflow: hidden; text-decoration: none; color: #fff; text-align: left;
  transition: transform 180ms var(--ease-out), filter 180ms linear;
}
.widget--ssc { background: #fff }
.widget--ssc img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 50% }
.widget--glass {
  padding: 3.8cqi 4.2cqi 3.6cqi;
  background: rgba(255, 255, 255, .13);
  box-shadow: inset 0 0 0 .3cqi rgba(255, 255, 255, .14), inset 0 .35cqi 0 rgba(255, 255, 255, .22);
}
.widget__k   { font: 600 3.2cqi/1.2 var(--font-text); color: rgba(255, 255, 255, .72) }
.widget__big {
  margin-top: auto; font: 600 12cqi/1 var(--font-display); letter-spacing: -.02em;
  background: linear-gradient(90deg, #64d2ff, #bf5af2 45%, #ff5e7e 75%, #ffb340);
  -webkit-background-clip: text; background-clip: text;
  color: transparent; -webkit-text-fill-color: transparent;
}
.widget__v { margin-top: .9cqi; font: 600 3.6cqi/1.2 var(--font-text) }
.widget__s { font: 400 3.1cqi/1.25 var(--font-text); color: rgba(255, 255, 255, .66) }

.home__grid {
  display: grid; grid-template-columns: repeat(4, 15.5cqi);
  justify-content: space-between; row-gap: 4.4cqi; margin-top: 5cqi;
}
.home__grid > li { display: flex; justify-content: center }
.hs-app { display: flex; flex-direction: column; align-items: center; width: 22cqi; border-radius: 3cqi }

/* Medium widget: four icons plus three gutters wide, one small widget tall. */
.hs-slot--wide { margin-top: 5cqi }
.widget--code {
  aspect-ratio: auto; height: 39.3cqi; padding: 3.6cqi 4.4cqi;
  background: #1d1d22;
  box-shadow: inset 0 0 0 .3cqi rgba(255, 255, 255, .08), inset 0 .35cqi 0 rgba(255, 255, 255, .1);
}
.code__file {
  display: flex; align-items: center; gap: 1.3cqi;
  font: 600 2.8cqi/1 var(--font-text); color: rgba(255, 255, 255, .5);
}
.code__file::before {
  content: ""; width: 2.6cqi; height: 2.6cqi; border-radius: .7cqi;
  background: linear-gradient(160deg, #ff9f0a, #ff375f);
}
.code {
  margin: auto 0 0; white-space: pre; overflow: hidden;
  font: 400 3.15cqi/1.5 var(--font-mono); letter-spacing: 0; color: rgba(255, 255, 255, .88);
}
.code .k { color: #ff7ab2; font-weight: 600 }
.code .t { color: #dabaff }
.code .m { color: #67d8c4 }

.home__dock {
  display: flex; justify-content: center; gap: 8.33cqi;
  margin-top: auto; padding: 3.2cqi; border-radius: 9.6cqi;
  background: rgba(255, 255, 255, .18);
  box-shadow: inset 0 0 0 .3cqi rgba(255, 255, 255, .14), inset 0 .35cqi 0 rgba(255, 255, 255, .26);
}
.dock-app { display: block; border-radius: 3.5cqi }

/* ═══ APP ICONS ═════════════════════════════════════════════════════════════
   One component at every size: the Home Screen, the App Store list, the app
   page. Radius 22.37% of the side, a top-lit specular sheen, a hairline
   so the pale ones still hold their edge on white.                        */
.app-icon {
  --s: 64px;
  position: relative; flex: none; display: grid; place-items: center;
  width: var(--s); height: var(--s); overflow: hidden;
  border-radius: calc(var(--s) * .2237);
  background: var(--ig, #8e8e93);
  box-shadow: inset 0 0 0 .5px rgba(0, 0, 0, .1), inset 0 1px 0 rgba(255, 255, 255, .3);
  transition: transform 220ms var(--spring), filter 160ms linear;
}
.app-icon::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: linear-gradient(160deg, rgba(255, 255, 255, .3), rgba(255, 255, 255, 0) 46%);
}
.app-icon svg { position: relative; z-index: 1; width: 58%; height: 58%;
                filter: drop-shadow(0 1px 1.2px rgba(0, 0, 0, .16)) }
.home .app-icon { --s: 15.5cqi }

/* The apps wear their real artwork (an <img>, so build_zip.py versions it).
   No sheen on top of someone else's art; the hairline moves above the image
   so the pale icons still hold their edge on white. */
.app-icon > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover }
.app-icon:has(> img)::after { background: none; box-shadow: inset 0 0 0 .5px rgba(0, 0, 0, .12) }

/* Per app: the artwork's ground colour. Shows while the image loads and
   fills the sheet's cover around the icon as it grows. */
.ig-hidden   { --ig: #ebe9dd }
.ig-doppel   { --ig: #1e1e1e }
.ig-ouzia    { --ig: #8cc63f }
.ig-aions    { --ig: #f8e3b5 }
.ig-becool   { --ig: #1f2742 }
.ig-shleep   { --ig: #fbf6e0 }
.ig-dummy    { --ig: #2b1d63 }
.ig-pov      { --ig: #7ea486 }
.ig-faraday  { --ig: #6aa3ad }
.ig-skin     { --ig: #f8ebe4 }
.ig-mail     { --ig: linear-gradient(180deg, #53b8ff 0%, #1a7cf5 100%) }
.ig-linkedin { --ig: linear-gradient(180deg, #1a86e4 0%, #0a66c2 100%) }
.ig-github   { --ig: linear-gradient(180deg, #33393f 0%, #0d1117 100%) }

/* Press and pointer states, iOS-style: icons dim and sink when pressed. */
@media (hover: hover) {
  .hs-app:hover .app-icon, .dock-app:hover .app-icon { transform: translateY(-.8cqi) scale(1.05) }
  .widget:hover { transform: scale(1.02) }
}
.hs-app:active .app-icon, .dock-app:active .app-icon,
.applist__row:active .app-icon { transform: scale(.9); filter: brightness(.82) }
.widget:active { transform: scale(.96); filter: brightness(.9) }
.hs-app:focus-visible, .dock-app:focus-visible, .widget:focus-visible {
  outline: 2px solid #fff; outline-offset: .8cqi;
}

/* A row in the App Store list lights up its icon on the phone. */
.hs-app.is-hot .app-icon {
  transform: translateY(-.8cqi) scale(1.08);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .3),
              0 0 0 .6cqi rgba(255, 255, 255, .9), 0 2cqi 5cqi rgba(0, 0, 0, .35);
}

/* Unlock: the Home Screen settles into place, icons nearest the centre
   first. JS adds .is-asleep at boot and removes it on first sight, so with
   no JS (or reduced motion) nothing is ever hidden. */
.hs-anim {
  transition: opacity 520ms var(--ease-out) var(--hs-d, 0ms),
              transform 900ms var(--spring) var(--hs-d, 0ms);
}
.home.is-asleep .hs-anim { opacity: 0; transform: scale(1.28) }
.home.is-asleep::before  { transform: scale(1.14) }

/* ═══ APPLE INTELLIGENCE GLOW ═══════════════════════════════════════════════
   Two rings on the glass edge (a crisp line and a soft inner bloom) and a
   halo behind the device. Each is a masked or clipped window onto a conic
   gradient that turns underneath it.                                      */
@keyframes aiSpin    { to { rotate: 360deg } }
@keyframes aiBreathe { 0%, 100% { opacity: .55 } 50% { opacity: 1 } }

.ai-edge { position: absolute; inset: 0; z-index: 6; border-radius: inherit; pointer-events: none }
.ai-ring {
  position: absolute; inset: 0; overflow: hidden; border-radius: inherit;
  padding: 1cqi;
  -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 exclude, linear-gradient(#000 0 0);
}
.ai-ring::before, .ai-halo::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 250cqi; aspect-ratio: 1; translate: -50% -50%;
  background: var(--ai-conic);
  animation: aiSpin 6s linear infinite;
}
/* The bloom: four edge fades instead of a blur, so nothing re-filters
   per frame; the screen's own rounded clip shapes the corners. */
.ai-ring--soft {
  padding: 0;
  -webkit-mask:
    linear-gradient(to bottom, #000, transparent) top    / 100% 8cqi no-repeat,
    linear-gradient(to top,    #000, transparent) bottom / 100% 8cqi no-repeat,
    linear-gradient(to right,  #000, transparent) left   / 8cqi 100% no-repeat,
    linear-gradient(to left,   #000, transparent) right  / 8cqi 100% no-repeat;
  -webkit-mask-composite: source-over;
          mask:
    linear-gradient(to bottom, #000, transparent) top    / 100% 8cqi no-repeat,
    linear-gradient(to top,    #000, transparent) bottom / 100% 8cqi no-repeat,
    linear-gradient(to right,  #000, transparent) left   / 8cqi 100% no-repeat,
    linear-gradient(to left,   #000, transparent) right  / 8cqi 100% no-repeat;
          mask-composite: add;
  animation: aiBreathe 4.5s ease-in-out infinite;
}

/* The clip box bounds the halo's spin for Chrome (see .aura-clip), with 92px
   of room on every side so the blur's spread is never cut. The halo sits in it
   at exactly its old place: 1% top/bottom, -5% left/right of the phone. */
.ai-halo-clip {
  position: absolute; z-index: 0; inset: calc(1% - 92px) calc(-5% - 92px);
  overflow: clip; pointer-events: none;
}
.ai-halo {
  position: absolute; inset: 92px;
  border-radius: 22%; overflow: hidden;
  container-type: inline-size;
  filter: blur(46px); opacity: var(--halo-o);
}
.ai-halo::before { animation-duration: 14s }
@media (max-width: 734px) { .ai-halo { filter: blur(32px) } }

/* Off screen the glow is removed, not paused: a paused animation still holds
   its ~1000px GPU layer, and Chrome then promotes everything drawn over the
   area it could sweep into layers of its own. Back on screen it restarts at
   0deg, unseen. Under an open sheet or viewer the phone still shows, so there
   it pauses instead of jumping. */
.is-paused .ai-ring::before, .is-paused .ai-halo::before, .is-paused .ai-ring--soft { animation: none }
body.is-locked .ai-ring::before, body.is-locked .ai-halo::before, body.is-locked .ai-ring--soft {
  animation-play-state: paused;
}

/* ═══ HERO · her portrait in front of an Apple Intelligence aura ═══════════
   A circle of the glow colours, blurred and faded by a radial mask so it has
   no edge at all; it turns slowly (the `rotate` property, compositor only).
   The portrait fades out at the bottom instead of stopping on a hard line. */
.hero { overflow-x: clip }
.hero__stage { max-width: 500px }
.hero__aura { position: relative; isolation: isolate; aspect-ratio: 4 / 5 }
/* Baked: assets/img/aura.jpg is this circle (the conic, its radial fade,
   blur(26px), opacity .62) rendered once on the page white; the recipe is in
   the README. Spinning the live gradient made Chrome re-mask and re-blur it
   every frame (~85% of the hero's idle CPU); spinning a plain image costs the
   compositor nothing. Blur and a radial fade are rotation-invariant, so the
   bitmap turns exactly as the gradient did. */
/* The clip box bounds the spin for Chrome. Without it Chrome can't tell how
   far a rotating layer reaches, assumes it overlaps everything after it on the
   page, and promotes the next sections into layers of their own. The circle
   never leaves its square, so the clip changes nothing you can see. */
.aura-clip {
  position: absolute; z-index: 0; left: 50%; top: 44%;
  width: 104%; aspect-ratio: 1; translate: -50% -50%;
  overflow: clip; pointer-events: none;
}
.aura {
  display: block; width: 100%; height: 100%; max-width: none;
  border-radius: 50%;
  animation: aiSpin 18s linear infinite;
}
.hero__aura picture { display: contents }
.hero__portrait {
  position: absolute; z-index: 1; left: 50%; bottom: 0; translate: -50% 0;
  width: 90%; max-width: none; height: auto;
  /* Eased (smoothstep) fade: a linear ramp ends in a visible line where its
     slope stops. Fully clear by 93%, above row 1448 of 1536, where her thigh
     touches the photo's left edge, so that straight cut never shows. */
  --fade: linear-gradient(to bottom,
      #000 66%, rgba(0, 0, 0, .97) 68.7%, rgba(0, 0, 0, .9) 71.4%, rgba(0, 0, 0, .78) 74.1%,
      rgba(0, 0, 0, .65) 76.8%, rgba(0, 0, 0, .5) 79.5%, rgba(0, 0, 0, .35) 82.2%,
      rgba(0, 0, 0, .22) 84.9%, rgba(0, 0, 0, .1) 87.6%, rgba(0, 0, 0, .03) 90.3%, transparent 93%);
  -webkit-mask-image: var(--fade);
          mask-image: var(--fade);
  transition: opacity var(--t-slide) var(--ease);
}
.hero__aura img.is-loading { opacity: 0 }       /* popGate */
.is-paused .aura { animation: none }                  /* off screen: drop the layer (see the glow) */
body.is-locked .aura { animation-play-state: paused }
html.reduced-motion .aura { animation: none }
@media (prefers-reduced-motion: reduce) { .aura { animation: none } }
@media (max-width: 1068px) { .hero__stage { max-width: 460px; margin-top: 96px } }
@media (max-width:  734px) { .hero__stage { max-width: 100%; margin-top: 72px } }

/* ═══ APPS · the big phone beside the App Store list ════════════════════════ */
#apps { overflow-x: clip }
.apps { align-items: center; row-gap: 0 }
.apps__head  { grid-column: 7 / span 6; grid-row: 1; align-self: end; padding-bottom: 28px }
.apps__stage { grid-column: 1 / span 5; grid-row: 1 / span 2;
               display: flex; flex-direction: column; align-items: center }
.apps__list  { grid-column: 7 / span 6; grid-row: 2; align-self: start }
.apps__deck  { margin-top: 20px }
.apps__hint  { margin-top: 28px; text-align: center }
@media (max-width: 1068px) {
  .apps__head, .apps__stage, .apps__list { grid-column: 1 / -1; grid-row: auto }
  .apps__head  { padding-bottom: 0 }
  .apps__stage { margin-top: 64px }
  .apps__list  { margin-top: 56px }
}
@media (max-width: 734px) {
  .apps__stage { margin-top: 48px }
  .apps__list  { margin-top: 40px }
  .apps__hint  { margin-top: 22px }
}

.applist { display: grid; grid-template-columns: minmax(0, 1fr) }
.applist > li { position: relative; min-width: 0 }
/* Separators inset to the text origin, never above the first row. */
.applist > li + li::before {
  content: ""; position: absolute; top: 0; right: 0; left: 80px;
  height: 1px; background: rgba(0, 0, 0, .1);
}
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
  .applist > li::before { height: .5px; background: var(--hairline-ios) }
}

.applist__row {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; column-gap: 16px;
  width: 100%; padding: 14px 0; text-align: left; border-radius: var(--r-tile);
}
.applist__row:focus-visible { outline-offset: 4px }
.applist__text { display: flex; flex-direction: column; min-width: 0 }
.applist__name, .applist__sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis }
.applist__name { font: 600 17px/22px var(--font-text); letter-spacing: var(--ls-17); color: var(--ink) }
.applist__sub  { margin-top: 2px; font: 400 14px/20px var(--font-text); letter-spacing: var(--ls-14); color: var(--ink-2) }
.applist__get {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 72px; height: 30px; padding: 0 16px; border-radius: var(--r-pill);
  background: var(--fill-3); color: var(--link);
  font: 600 14px/1 var(--font-text); letter-spacing: var(--ls-14);
  transition: background var(--t-hover) linear;
}
.applist__row:hover .applist__get { background: var(--fill-2) }
@media (max-width: 734px) {
  .applist .app-icon { --s: 56px }
  .applist > li::before { left: 72px }
}

/* Pages of five, swiped (scroll-snap) or stepped with the slideshow's
   paddles and dots, like an App Store shelf. The 6px of padding gives the
   rows' focus rings room inside the scroller. */
.applist__pages {
  position: relative; display: grid; grid-auto-flow: column; grid-auto-columns: 100%; column-gap: 40px;
  overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scrollbar-width: none;
  margin: -6px; padding: 6px; scroll-padding-inline: 6px;
}
.applist__pages::-webkit-scrollbar { display: none }
.applist__pages > .applist { align-self: start; scroll-snap-align: start; scroll-snap-stop: always }
.applist__pager { display: flex; align-items: center; justify-content: center; gap: 16px; margin-top: 16px }

/* ═══ APP SHEET ═════════════════════════════════════════════════════════════
   A centred card on desktop, a bottom sheet on iPhone widths. JS grows it
   out of the icon that was tapped (transform + clip-path, FLIP).          */
.appsheet { position: fixed; inset: 0; z-index: 150; display: grid; place-items: center; padding: 24px }
.appsheet[hidden] { display: none }
.appsheet__backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, .4) }

.appsheet__panel {
  position: relative; z-index: 1; display: flex; flex-direction: column;
  width: min(760px, 100%); height: min(88vh, 900px);
  border-radius: var(--r-card); overflow: hidden; outline: none;
  background: var(--page); color: var(--ink);
  box-shadow: 0 40px 90px -30px rgba(0, 0, 0, .5);
  transform-origin: 0 0;
}
@supports (height: 1svh) { .appsheet__panel { height: min(88svh, 900px) } }
@media (max-width: 734px) {
  .appsheet { padding: 0; place-items: end stretch }
  .appsheet__panel { width: 100%; height: 92vh; border-radius: var(--r-card) var(--r-card) 0 0 }
  @supports (height: 1svh) { .appsheet__panel { height: 92svh } }
}

.appsheet__grabber {
  display: none; position: absolute; z-index: 3; top: 6px; left: 50%; transform: translateX(-50%);
  width: 36px; height: 5px; border-radius: 3px; background: var(--hairline);
}
@media (max-width: 734px) { .appsheet__grabber { display: block } }

.appsheet__close {
  position: absolute; z-index: 3; top: 16px; right: 16px;
  width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--fill-3); color: var(--ink-2);
  transition: background var(--t-hover) linear;
}
.appsheet__close::before {        /* 44px hit area on a 30px control */
  content: ""; position: absolute; inset: -7px; border-radius: 50%;
}
.appsheet__close:hover { background: var(--fill-2) }

.appsheet__scroll {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  padding: 40px 40px 56px;
}
@media (max-width: 734px) { .appsheet__scroll { padding: 34px 20px 44px } }

/* The icon's own face, laid over the panel while it grows; fades as the
   page arrives. --sq is set by JS to the side of the square that starts
   out exactly the size of the tapped icon. */
.appsheet__cover { position: absolute; inset: 0; z-index: 5; background: var(--ig); opacity: 0; pointer-events: none }
.appsheet__art {
  position: absolute; left: 50%; top: 0; translate: -50% 0;
  width: var(--sq, 0px); height: var(--sq, 0px); object-fit: cover;
}

/* ── App page ── */
.apppage__head {
  display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center;
  column-gap: 24px; padding-right: 36px;
}
.apppage__head .app-icon { --s: 118px }
.apppage__name { font: 600 28px/32px var(--font-display); letter-spacing: var(--ls-28) }
.apppage__sub  { margin-top: 4px; font: 400 17px/22px var(--font-text); letter-spacing: var(--ls-17); color: var(--ink-2) }
.apppage__platform {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 12px;
  font: 400 12px/16px var(--font-text); letter-spacing: var(--ls-12); color: var(--ink-2);
}
.apppage__platform svg { width: 14px; height: 14px; flex: none }
@media (max-width: 734px) {
  .apppage__head { column-gap: 16px; padding-right: 28px }
  .apppage__head .app-icon { --s: 96px }
  .apppage__name { font-size: 24px; line-height: 28px; letter-spacing: var(--ls-24) }
}

/* The App Store's information strip. */
.appstrip {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  margin-top: 28px; padding-block: 14px;
  border-top: 1px solid var(--hairline-ios); border-bottom: 1px solid var(--hairline-ios);
}
.appstrip > div { min-width: 0; padding: 0 10px; text-align: center }
.appstrip > div + div { border-left: 1px solid var(--hairline-ios) }
.appstrip dt, .appstrip dd { white-space: nowrap; overflow: hidden; text-overflow: ellipsis }
.appstrip dt { font: 400 12px/16px var(--font-text); letter-spacing: var(--ls-12); color: var(--ink-2) }
.appstrip__v { margin-top: 4px; font: 600 21px/25px var(--font-display); letter-spacing: var(--ls-21); color: var(--ink-2) }
.appstrip__u { margin-top: 2px; font: 400 12px/16px var(--font-text); letter-spacing: var(--ls-12); color: var(--ink-2) }
@media (max-width: 734px) {
  .appstrip {
    grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: 38%;
    overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
    margin-inline: -20px; padding-inline: 10px;
  }
  .appstrip::-webkit-scrollbar { display: none }
}

/* Blocks are <section>s for their headings; they must not inherit the page's
   112px section padding. */
.apppage__block { margin-top: 32px; padding-block: 0; scroll-margin-top: 0 }
.apppage__h { margin-bottom: 14px; font: 600 21px/25px var(--font-display); letter-spacing: var(--ls-21) }
.apppage .prose { max-width: 62ch }
.apppage__lede { margin-bottom: 14px }

/* Screenshots: raw, corner-rounded, scrolling sideways — as on the store. */
.shots {
  display: grid; grid-auto-flow: column; grid-auto-columns: max-content; gap: 12px;
  overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory;
  scrollbar-width: none;
  margin: -6px -40px; padding: 6px 40px; scroll-padding-inline: 40px;
}
.shots::-webkit-scrollbar { display: none }
.shot { position: relative; scroll-snap-align: start; overflow: hidden; border-radius: var(--r-tile); background: #000 }
.shot::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08);
}
.shot img { height: var(--sh); width: auto; max-width: none; transition: transform 300ms var(--ease-out) }
.shot:hover img, .shot:focus-visible img { transform: scale(1.0161) }
.shot:focus-visible { outline-offset: 2px }
.shots--43   { --sh: 300px }
.shots--land { --sh: 200px }
.shots--tall { --sh: 400px }
.shots--tall .shot { border-radius: 24px }
.shots--watch { --sh: 360px }
.shots--watch .shot { border-radius: 22% / 18% }    /* the Watch display’s own corners */
@media (max-width: 734px) {
  .shots { margin-inline: -20px; padding-inline: 20px; scroll-padding-inline: 20px }
  .shots--43 { --sh: 210px } .shots--land { --sh: 150px } .shots--tall { --sh: 340px } .shots--watch { --sh: 300px }
}

/* Paddles over each screenshot row, for a mouse that can't scroll sideways.
   JS adds them; touch already swipes, so touch-only screens never see them.
   Each one bows out at its end of the row, both when the row fits. */
.shots-wrap { position: relative }
.shots__paddle {
  position: absolute; z-index: 2; top: 50%; translate: 0 -50%;
  background: rgba(255, 255, 255, .94); color: var(--ink);
  box-shadow: 0 0 0 .5px rgba(0, 0, 0, .14);
  transition: opacity 200ms linear, background var(--t-hover) linear;
}
.shots__paddle:hover  { background: #fff; color: var(--ink) }
.shots__paddle:active { background: #ececf0 }
.shots__paddle[disabled] { opacity: 0 }
.shots__paddle--prev { left: -36px }
.shots__paddle--next { right: -36px }
@media (max-width: 734px) { .shots__paddle--prev { left: -16px } .shots__paddle--next { right: -16px } }
@media (hover: none) { .shots__paddle { display: none } }

.appinfo > div {
  display: flex; justify-content: space-between; align-items: baseline; gap: 24px;
  padding-block: 12px; border-top: 1px solid var(--hairline-ios);
}
.appinfo > div:first-child { border-top: 0; padding-top: 0 }
.appinfo dt { flex: none; font: 400 14px/20px var(--font-text); letter-spacing: var(--ls-14); color: var(--ink-2) }
.appinfo dd { font: 400 14px/20px var(--font-text); letter-spacing: var(--ls-14); color: var(--ink); text-align: right }

/* ═══ STATS · widget cards ══════════════════════════════════════════════════ */
.impact .stats { gap: 20px; padding-top: 48px }
.stat {
  background: var(--surface); border: 1px solid var(--card-stroke);
  border-radius: var(--r-card); padding: 28px 28px 30px;
}
.stat .t-stat { display: inline-block }
@media (max-width: 734px) {
  .impact .stats { gap: 12px; padding-top: 32px }
  .stat + .stat { border-top: 1px solid var(--card-stroke); margin-top: 0; padding-top: 28px }
}

/* ═══ AI FIELD · the colour behind both portraits (hero, About) ═══════════ */
.about__frame.plate { aspect-ratio: 6 / 7; --pw: 112% }
/* Edge to edge from tablet down, square-cornered like a band. Tablet goes
   landscape (a full-width square would swallow the screen) and the portrait
   narrows so the head still rises ~6% above the plate; phones keep 1:1. */
@media (max-width: 1068px) {
  .about__frame.plate { aspect-ratio: 4 / 3; --pw: 72%; border: 0; border-radius: 0 }   /* full-bleed band */
  .about__frame .frame-pop { border-radius: 0 }
}
@media (max-width: 734px)  { .about__frame.plate { aspect-ratio: 1 / 1; --pw: 96% } }
.ai-field {
  position: absolute; inset: -14%;
  background:
    radial-gradient(60% 50% at 24% 22%, rgba(94, 92, 230, .34), transparent 70%),
    radial-gradient(55% 45% at 82% 30%, rgba(191, 90, 242, .28), transparent 70%),
    radial-gradient(60% 50% at 72% 86%, rgba(255, 55, 95, .24), transparent 70%),
    radial-gradient(50% 42% at 18% 80%, rgba(255, 159, 10, .22), transparent 70%);
  filter: blur(36px);
}

/* ═══ CONTACT · her contact card ════════════════════════════════════════════ */
#contact { overflow-x: clip }
.contact { align-items: center }
.contact__copy  { grid-column: 1 / span 6 }
.contact__stage { grid-column: 8 / span 5; display: flex; justify-content: center }
.contact__copy .t-section { margin-top: 8px }
.contact__copy .t-intro { margin-top: 24px }
.contact__copy .contact__actions { justify-content: flex-start }
@media (max-width: 1068px) {
  .contact__copy, .contact__stage { grid-column: 1 / -1 }
  .contact__stage { margin-top: 64px }
}
@media (min-width: 1069px) { .phone-wrap--cc .phone { --dw: 360px } }

.cc {
  --cc-bg: #f2f2f7; --cc-cell: #ffffff; --cc-ink: #000000;
  --cc-link: #007aff; --cc-sep: rgba(60, 60, 67, .2);
  display: flex; flex-direction: column; background: var(--cc-bg); color: var(--cc-ink);
}

/* Poster: name first (z1), portrait over it (z2), so her head passes in
   front of the letters. Geometry: crown sits ~1.4% below the image top. */
.poster {
  position: relative; flex: none; height: 142cqi; overflow: hidden;
  background:
    radial-gradient(80% 55% at 18% 14%, rgba(100, 210, 255, .5), transparent 62%),
    linear-gradient(165deg, #5e5ce6 0%, #bf5af2 38%, #ff375f 72%, #ff9f0a 100%);
}
.poster::after {
  content: ""; position: absolute; inset: 52% 0 0; z-index: 3; pointer-events: none;
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, .5));
}
.poster__name {
  position: absolute; z-index: 1; left: 0; right: 0; top: 16.5cqi;
  text-align: center; color: #fff;
  font: 600 20cqi/1 var(--font-display); letter-spacing: -.03em;
}
.poster picture { display: contents }
.poster__photo {
  position: absolute; z-index: 2; left: 50%; bottom: 0; translate: -50% 0;
  width: 78cqi; max-width: none; height: auto;
  transition: opacity var(--t-slide) var(--ease);
}
.poster img.is-loading { opacity: 0 }
.poster__role {
  position: absolute; z-index: 4; left: 0; right: 0; bottom: 21cqi;
  text-align: center; font: 600 3.8cqi/1.2 var(--font-text); color: rgba(255, 255, 255, .94);
}

.cc__actions {
  position: relative; z-index: 5; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 2.4cqi; margin: -16.5cqi 5cqi 0;
}
.cc__btn {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1.1cqi;
  height: 13cqi; border-radius: 3.6cqi; text-decoration: none; color: #fff;
  background: rgba(255, 255, 255, .22);
  box-shadow: inset 0 .3cqi 0 rgba(255, 255, 255, .26), inset 0 0 0 .25cqi rgba(255, 255, 255, .12);
  font: 400 2.9cqi/1 var(--font-text);
}
.cc__btn svg { width: 5.4cqi; height: 5.4cqi }
.cc__btn:hover { background: rgba(255, 255, 255, .3) }
.cc__btn:focus-visible, .cc__row:focus-visible { outline: 2px solid var(--cc-link); outline-offset: .6cqi }

.cc__rows { margin: 4.4cqi 5cqi 0; border-radius: 3.6cqi; background: var(--cc-cell); overflow: hidden }
.cc__row { position: relative; display: block; padding: 2.6cqi 4cqi; color: inherit; text-decoration: none }
.cc__row + .cc__row::before {
  content: ""; position: absolute; top: 0; left: 4cqi; right: 0; height: 1px; background: var(--cc-sep);
}
.cc__k { display: block; font: 400 3.1cqi/1.35 var(--font-text); color: var(--cc-ink) }
.cc__v {
  display: block; font: 400 3.8cqi/1.35 var(--font-text); color: var(--cc-link);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cc__notes { margin-top: 3.6cqi }
.cc__note { display: block; font: 400 3.8cqi/1.35 var(--font-text); color: var(--cc-ink) }
.cc .phone__indicator { background: var(--cc-ink) }

/* ═══ SCROLL LOCK · no layout jump when a sheet opens ═══════════════════════ */
html { scrollbar-gutter: stable }

/* ═══ REDUCED MOTION / CONTRAST / PRINT ═════════════════════════════════════ */
html.reduced-motion .ai-ring::before,
html.reduced-motion .ai-halo::before,
html.reduced-motion .ai-ring--soft { animation: none }
@media (prefers-reduced-motion: reduce) {
  .ai-ring::before, .ai-halo::before, .ai-ring--soft { animation: none }
  .hs-anim, .home::before, .app-icon, .widget, .applist__get, .shot img { transition: none }
  .hs-app:hover .app-icon, .dock-app:hover .app-icon, .widget:hover,
  .shot:hover img, .shot:focus-visible img { transform: none }
}
@media (forced-colors: active) {
  .ai-halo, .ai-edge { display: none }
  .app-icon, .phone, .widget { forced-color-adjust: none }
}
@media print {
  .appsheet, .ai-halo, .ai-edge { display: none !important }
}
