/* sheawilson.uk
   Concept: a gallery lit by the work. Light mode is daylight: a white disc ringed with colour,
   glass cards with each project's light bleeding through. Dark mode keeps the same colour,
   turned up, behind smoked glass.
   Performance: nothing that moves carries a CSS blur filter. Soft edges come from gradients and masks. */

@property --p1 { syntax: '<color>'; inherits: true; initial-value: #ed1652; }
@property --p2 { syntax: '<color>'; inherits: true; initial-value: #ff6a1a; }
@property --p3 { syntax: '<color>'; inherits: true; initial-value: #ffb22c; }
@property --p4 { syntax: '<color>'; inherits: true; initial-value: #43d9ff; }
@property --p5 { syntax: '<color>'; inherits: true; initial-value: #8a3cff; }
@property --p6 { syntax: '<color>'; inherits: true; initial-value: #3a17e0; }
@property --umbra { syntax: '<length>'; inherits: false; initial-value: 0px; }

:root {
  color-scheme: light;
  --bg: #ffffff;
  --ink: #0a0a0a;
  --ink-2: rgba(10, 10, 10, .64);
  --whisper: rgba(10, 10, 10, .46);
  --hair: rgba(10, 10, 10, .08);
  --glass: rgba(255, 255, 255, .6);
  --glass-strong: rgba(255, 255, 255, .78);
  --glass-edge: rgba(255, 255, 255, .92);
  --glass-line: rgba(10, 10, 10, .07);
  --shadow-rest: 0 1px 2px rgba(10, 10, 10, .04), 0 12px 34px rgba(10, 10, 10, .05);
  --shadow-hover: 0 2px 6px rgba(10, 10, 10, .05), 0 24px 60px rgba(10, 10, 10, .1);
  --bleed-rest: .55;
  --bleed-hover: 1;
  --bleed-blend: normal;
  --sheen: rgba(255, 255, 255, .45);
  --disc: #ffffff;
  --pale-a: #fde9cf;
  --pale-b: #e3ebff;
  --nav-glass: rgba(255, 255, 255, .5);
  --nav-edge: rgba(255, 255, 255, .55);

  --ease: cubic-bezier(.2, .9, .25, 1);
  --ease-io: cubic-bezier(.65, 0, .35, 1);
  --serif: 'Spectral', Georgia, serif;
  --sans: 'DM Sans', system-ui, -apple-system, sans-serif;
  --gutter: clamp(20px, 4vw, 56px);
  /* Squircle corners: continuous curves that start earlier. Plain rounded corners where unsupported. */
  /* Display type: Spectral is spaced for reading sizes, so the bigger it gets the tighter it's set */
  --track-display: -.03em;
  --track-heading: -.022em;
  --track-title: -.018em;
  --word-display: -.04em;
  --radius: 56px;
  --radius-sm: 34px;
}
@supports not (corner-shape: squircle) { :root { --radius: 34px; --radius-sm: 22px; } }

[data-theme="dark"] {
  color-scheme: dark;
  --bg: #05070b;
  --ink: #f2f0eb;
  --ink-2: rgba(242, 240, 235, .68);
  --whisper: rgba(242, 240, 235, .44);
  --hair: rgba(242, 240, 235, .09);
  --glass: rgba(18, 21, 28, .55);
  --glass-strong: rgba(18, 20, 27, .8);
  --glass-edge: rgba(255, 255, 255, .09);
  --glass-line: rgba(255, 255, 255, .08);
  --shadow-rest: 0 24px 60px rgba(0, 0, 0, .45);
  --shadow-hover: 0 30px 80px rgba(0, 0, 0, .55);
  --bleed-rest: .62;
  --bleed-hover: 1;
  --bleed-blend: normal;
  --sheen: rgba(255, 255, 255, .06);
  --disc: #030409;
  --pale-a: #3a2a22;
  --pale-b: #1c2436;
  --nav-glass: rgba(16, 18, 24, .45);
  --nav-edge: rgba(255, 255, 255, .06);
}

* { box-sizing: border-box; margin: 0; padding: 0; }
:is(.card, .t-small .media, .screen) { corner-shape: squircle; }
html { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; scroll-behavior: smooth; background: var(--bg); overflow-x: clip; }
body { background: var(--bg); color: var(--ink); font-family: var(--sans); font-weight: 300; overflow-x: clip; transition: background-color .6s var(--ease), color .6s var(--ease); }
a { color: inherit; text-decoration: none; }
img, video { display: block; max-width: 100%; height: auto; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
::selection { background: color-mix(in srgb, var(--p1) 22%, transparent); }
.theme-switching *, .theme-switching *::before, .theme-switching *::after { transition: none !important; }

.label { font-size: 13px; font-weight: 400; line-height: 1.4; color: var(--whisper); }
.live { display: inline-flex; align-items: center; gap: 8px; }
.live::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: #2fd67b; animation: pulse 2.4s var(--ease) infinite; }
@keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(47, 214, 123, .45); } 70%, 100% { box-shadow: 0 0 0 9px rgba(47, 214, 123, 0); } }

/* ───────── Project tip ───────── */
.tip { position: fixed; left: 0; top: 0; z-index: 100; pointer-events: none; display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 12px 6px 10px; border-radius: 999px; font-size: 12px; font-weight: 500; letter-spacing: -.005em; white-space: nowrap; color: var(--ink);
  background: var(--glass-strong); border: 1px solid var(--glass-edge); box-shadow: 0 10px 30px rgba(0, 0, 0, .12);
  -webkit-backdrop-filter: blur(16px) saturate(1.6); backdrop-filter: blur(16px) saturate(1.6);
  opacity: 0; scale: .94; transform-origin: 0% 100%; transition: opacity .4s var(--ease), scale .5s var(--ease); will-change: transform; }
.tip.is-on { opacity: .92; scale: 1; }
.tip i { width: 7px; height: 7px; border-radius: 50%; background: #2fd67b; flex: none; }
.tip svg { width: 12px; height: 12px; flex: none; }

/* ───────── Nav ─────────
   The pill is its own layer that changes width; the name and links glide into it with transforms,
   so nothing in the bar reflows while it shrinks or grows. */
.nav { position: fixed; inset: 0 0 auto; z-index: 50; padding: 18px var(--gutter); pointer-events: none; }
.nav-inner { position: relative; pointer-events: auto; margin: 0 auto; max-width: 1380px; height: 52px; display: flex; align-items: center; justify-content: space-between; gap: 24px; }
.nav-pill { position: absolute; left: 50%; top: 0; bottom: 0; width: 100%; translate: -50% 0; border-radius: 999px; pointer-events: none; opacity: 0;
  background: var(--nav-glass); border: 1px solid var(--nav-edge); box-shadow: 0 8px 32px rgba(0, 0, 0, .06);
  -webkit-backdrop-filter: blur(24px) saturate(1.8); backdrop-filter: blur(24px) saturate(1.8);
  transition: width .8s var(--ease), opacity .45s var(--ease); }
.nav.is-scrolled .nav-pill { width: var(--pill-w, 460px); opacity: 1; }
.logo, .links { position: relative; z-index: 1; transition: transform .8s var(--ease); }
.nav.is-scrolled .logo { transform: translate3d(var(--logo-shift, 0px), 0, 0); }
.nav.is-scrolled .links { transform: translate3d(calc(-1 * var(--links-shift, 0px)), 0, 0); }
.logo { display: inline-flex; align-items: baseline; font-family: var(--serif); font-size: 22px; font-style: italic; font-weight: 400; letter-spacing: -.01em; white-space: nowrap; }
.fold { display: inline-grid; grid-template-columns: 1fr; transition: grid-template-columns .7s var(--ease); }
.fold > span { min-width: 0; overflow: hidden; padding-right: .08em; margin-right: -.08em; transition: opacity .45s var(--ease); }
.nav.is-scrolled .fold { grid-template-columns: 0fr; }
.nav.is-scrolled .fold > span { opacity: 0; }
.nav.is-scrolled .logo:hover .fold, .nav.is-scrolled .logo:focus-visible .fold { grid-template-columns: 1fr; }
.nav.is-scrolled .logo:hover .fold > span, .nav.is-scrolled .logo:focus-visible .fold > span { opacity: 1; }
.links { display: flex; align-items: center; gap: 26px; font-size: 14px; font-weight: 400; }
.links a { color: var(--ink-2); transition: color .3s var(--ease); }
.links a:hover { color: var(--ink); }

.theme-toggle { position: relative; width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center; }
.tt { position: relative; width: 18px; height: 18px; border-radius: 50%; }
.tt-ring { position: absolute; inset: -3px; border-radius: 50%;
  background: conic-gradient(from 0deg, #ed1652, #ff6a1a, #ffb22c, #43d9ff, #8a3cff, #3a17e0, #ed1652);
  -webkit-mask: radial-gradient(closest-side, transparent 62%, #000 72%, transparent 100%); mask: radial-gradient(closest-side, transparent 62%, #000 72%, transparent 100%);
  transition: transform 1s var(--ease); }
.tt-disc { position: absolute; inset: 1px; border-radius: 50%; background: #fff; overflow: hidden; box-shadow: 0 0 0 .5px rgba(10, 10, 10, .12); }
.tt-moon { position: absolute; inset: 0; border-radius: 50%; background: #05070b; transform: translateX(-115%); transition: transform .8s var(--ease-io); }
.theme-toggle:hover .tt-ring { transform: rotate(180deg); }
[data-theme="dark"] .tt-moon { transform: none; }

::view-transition-old(root), ::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
::view-transition-new(root) {
  -webkit-mask-image: radial-gradient(circle at var(--vx, 90%) var(--vy, 4%), #000 var(--umbra), transparent calc(var(--umbra) + 220px));
          mask-image: radial-gradient(circle at var(--vx, 90%) var(--vy, 4%), #000 var(--umbra), transparent calc(var(--umbra) + 220px));
  animation: umbra 1.15s var(--ease-io) both; }
@keyframes umbra { from { --umbra: -220px; } to { --umbra: 160vmax; } }

/* ───────── Hero: the horizon ─────────
   A huge disc rises from below and the page is its surface. The ring sits under the words and the disc
   sits over them, so scrolling carries the disc (and the first card on it) up over the headline. */
.scene { position: relative; height: calc(100svh + var(--travel, 110svh)); }
.hero { position: sticky; top: 0; height: 100svh; min-height: 620px; overflow: clip;
  transition: --p1 1.4s var(--ease), --p2 1.4s var(--ease), --p3 1.4s var(--ease), --p4 1.4s var(--ease), --p5 1.4s var(--ease), --p6 1.4s var(--ease); }
.hero[data-palette="snapshot"] { --p1: #ed1652; --p2: #ff6a1a; --p3: #c52bd6; --p4: #2f67ff; --p5: #3a17e0; --p6: #7a2cff; }
.hero[data-palette="heart"] { --p1: #ed1652; --p2: #ff4d6d; --p3: #7de8ff; --p4: #43d9ff; --p5: #08717d; --p6: #1fb3c9; }
.hero[data-palette="jumpstart"] { --p1: #0b5c45; --p2: #4fae86; --p3: #b8f0d2; --p4: #4fae86; --p5: #0b5c45; --p6: #8fd4b4; }
.hero[data-palette="brain"] { --p1: #8a3cff; --p2: #c77dff; --p3: #e2b8ff; --p4: #5b2bff; --p5: #3a17e0; --p6: #b44bff; }

/* No transform on the wrapper: the ring and the disc need separate layers in the page's stacking order */
.eclipse { position: absolute; left: calc(50% - 64vw); top: 66%; width: 128vw; aspect-ratio: 1; pointer-events: none; }
.corona { position: absolute; z-index: 3; inset: -9%; border-radius: 50%; will-change: transform;
  background: conic-gradient(from 0deg, var(--p1) 0deg, var(--p2) 36deg, var(--p3) 64deg, var(--pale-a) 96deg, var(--pale-b) 140deg,
    var(--p4) 182deg, var(--pale-b) 220deg, var(--p5) 256deg, var(--pale-a) 292deg, var(--p6) 326deg, var(--p1) 360deg);
  animation: turn 90s linear infinite;
  -webkit-mask: radial-gradient(closest-side, #000 75%, rgba(0, 0, 0, .86) 79%, rgba(0, 0, 0, .58) 84%, rgba(0, 0, 0, .3) 89%, rgba(0, 0, 0, .11) 94%, transparent 100%);
          mask: radial-gradient(closest-side, #000 75%, rgba(0, 0, 0, .86) 79%, rgba(0, 0, 0, .58) 84%, rgba(0, 0, 0, .3) 89%, rgba(0, 0, 0, .11) 94%, transparent 100%); }
.disc { position: absolute; z-index: 5; inset: 0; border-radius: 50%; background: var(--bg); will-change: transform; transition: background-color .6s var(--ease); }
[data-theme="dark"] .corona { opacity: .92; }
@keyframes turn { to { transform: rotate(1turn); } }

.hero-copy { position: absolute; z-index: 4; left: 50%; top: 36%; width: min(90vw, 940px); translate: -50% -50%; text-align: center; will-change: transform; }
.hero h1 { font-family: var(--serif); font-weight: 300; font-size: clamp(48px, 8vw, 124px); line-height: 1.08; letter-spacing: var(--track-display); word-spacing: var(--word-display); text-wrap: balance; }
.hero h1 em { font-style: italic; letter-spacing: var(--track-heading); }
.hero .intro { margin: 30px auto 0; max-width: 33em; font-size: clamp(17px, 1.35vw, 20px); line-height: 1.55; color: var(--ink-2); text-wrap: pretty; }
.recent { margin-top: 28px; display: flex; justify-content: center; flex-wrap: wrap; gap: 8px 22px; font-size: 14px; font-weight: 400; color: var(--ink-2); }
.recent > span { color: var(--whisper); }
.recent a { display: inline-flex; align-items: center; gap: 8px; transition: color .3s var(--ease); }
.recent a:hover, .recent a:focus-visible { color: var(--ink); }
.recent i { width: 7px; height: 7px; border-radius: 50%; background: var(--c); transition: box-shadow .5s var(--ease); }
.recent a:hover i { box-shadow: 0 0 0 4px color-mix(in srgb, var(--c) 22%, transparent); }
.recent .st { color: var(--whisper); }

/* ───────── Work ───────── */
.work { position: relative; z-index: 6; padding: 40px var(--gutter) 110px; max-width: 1380px; margin: calc(-1 * var(--overlap, 80svh)) auto 0; }

.grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 22px; }
.item { position: relative; isolation: isolate; }
.item > .card { height: 100%; }

/* The light behind the glass: soft ellipses over a shared wash. Only transforms change on hover. */
.bleed { position: absolute; inset: -5%; z-index: -1; pointer-events: none; opacity: var(--bleed-rest); mix-blend-mode: var(--bleed-blend); transition: opacity 1s var(--ease); }
.bleed::before { content: ""; position: absolute; inset: 12%; border-radius: 40%; filter: blur(50px); opacity: .55;
  background: conic-gradient(from var(--wash-from, 200deg), var(--a, transparent), var(--b, transparent), var(--c, transparent), var(--a, transparent)); }
.item.is-hot .bleed { opacity: var(--bleed-hover); }
.blob { position: absolute; border-radius: 50%; aspect-ratio: var(--ar, 1.5); will-change: transform;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--c) 78%, transparent) 0%, color-mix(in srgb, var(--c) 54%, transparent) 26%,
    color-mix(in srgb, var(--c) 30%, transparent) 48%, color-mix(in srgb, var(--c) 12%, transparent) 70%, color-mix(in srgb, var(--c) 3%, transparent) 88%, transparent 100%); }

/* The card draws its own lit border: an opaque base clipped to the inside, and the light clipped to the
   border ring, on one element with one corner shape. The colour and the glass tint sit inside as layers. */
@property --rimc { syntax: '<color>'; inherits: true; initial-value: transparent; }
.card { position: relative; isolation: isolate; display: flex; flex-direction: column; overflow: hidden; border-radius: var(--radius);
  border: 1px solid transparent; --rimc: var(--glass-edge);
  background: linear-gradient(var(--bg), var(--bg)) padding-box,
    radial-gradient(260px circle at var(--rx, 50%) var(--ry, -400px), var(--rimc), var(--glass-edge) 72%) border-box;
  box-shadow: var(--shadow-rest);
  transition: box-shadow .9s var(--ease), --rimc .6s var(--ease); }
.card::after { content: ""; position: absolute; inset: 0; z-index: 0; background: var(--glass); pointer-events: none; transition: background-color .6s var(--ease); }
.item { --rim: var(--tone, #8a93a8); }
[data-theme="dark"] .item { --rim: color-mix(in srgb, var(--tone, #ffffff) 72%, white); }
.item.is-hot .card { box-shadow: var(--shadow-hover); --rimc: var(--rim); }

.card-top { position: relative; z-index: 2; display: flex; justify-content: space-between; gap: 16px; padding: 30px 34px 0; }
.card-copy { position: relative; z-index: 2; padding: 16px 34px 0; }
.card h2 { font-family: var(--serif); font-weight: 300; font-size: clamp(30px, 2.6vw, 40px); line-height: 1.04; letter-spacing: var(--track-title); }
.card .line { margin-top: 10px; font-size: 16px; line-height: 1.5; color: var(--ink-2); max-width: 36ch; }
.media { position: relative; z-index: 1; flex: 1; will-change: transform; transform-style: preserve-3d; }

/* Snapshot */
.t-snapshot { grid-column: span 12; }
.t-snapshot .card { display: grid; grid-template-columns: 1.05fr 1fr; grid-template-rows: auto 1fr; min-height: 720px; }
.t-snapshot .card-top { grid-column: 1 / -1; padding: 36px 44px 0; }
.t-jump .card { grid-template-rows: auto 1fr; }
.t-jump .card-top { grid-column: 2; grid-row: 1; padding: 36px 48px 0 10px; }
.t-snapshot .card-copy { padding: 26px 44px 46px; display: flex; flex-direction: column; }
.t-snapshot h2, .t-jump h2 { font-size: clamp(42px, 4.6vw, 68px); letter-spacing: var(--track-heading); }
.t-snapshot .line, .t-jump .line { font-size: 18px; max-width: 32ch; }
.t-snapshot .media { position: relative; display: grid; place-items: center; padding-bottom: 30px; }
.t-snapshot .device { position: relative; z-index: 2; margin-left: 22%; height: min(600px, 62vw); width: auto; filter: drop-shadow(0 40px 60px rgba(20, 0, 80, .3)); }
.stats { margin-top: auto; display: grid; grid-template-columns: repeat(3, auto); justify-content: start; gap: 18px 46px; padding-top: 44px; }
.stat .num { display: block; font-family: var(--serif); font-weight: 200; font-size: clamp(46px, 4.8vw, 72px); line-height: 1; letter-spacing: -.02em; font-variant-numeric: tabular-nums lining-nums; }
.stat .what { display: block; margin-top: 10px; font-size: 13px; line-height: 1.45; font-weight: 400; color: var(--whisper); max-width: 17ch; }

.screen { position: absolute; border-radius: 16px; overflow: hidden; background: #fff; will-change: transform;
  box-shadow: 0 0 0 1px rgba(10, 10, 10, .06), 0 30px 70px rgba(10, 20, 60, .22); transition: transform 1.1s var(--ease); }
.screen img { width: 100%; height: auto; }
.snap-results { width: 72%; left: -4%; top: 22%; transform: rotate(-5deg); }
.item.is-hot .snap-results { transform: rotate(-7deg) translate3d(-5%, -3%, 0); }
[data-theme="dark"] .screen { background: #131314; box-shadow: 0 0 0 1px rgba(255, 255, 255, .08), 0 30px 70px rgba(0, 0, 0, .5); }

/* JumpStart */
.t-jump { grid-column: span 12; }
.t-jump .card { display: grid; grid-template-columns: 1.2fr 1fr; grid-template-rows: auto 1fr; min-height: 680px; }
.t-jump .media { position: relative; grid-column: 1; grid-row: 1 / -1; min-height: 600px; }
.t-jump .card-copy { grid-column: 2; grid-row: 2; padding: 26px 48px 46px 10px; display: flex; flex-direction: column; }
.screen-back { width: 68%; left: 3%; top: 5%; transform: rotate(-4deg); }
.screen-front { width: 54%; left: 33%; top: 25%; transform: rotate(1.5deg); }
.screen-export { width: 38%; left: 61%; top: 60%; transform: rotate(4deg); }
.item.is-hot .screen-back { transform: rotate(-6deg) translate3d(-5%, -4%, 0); }
.item.is-hot .screen-front { transform: rotate(2deg) translate3d(1%, 0, 0); }
.item.is-hot .screen-export { transform: rotate(6deg) translate3d(8%, 6%, 0); }
.img-dark { display: none !important; }
[data-theme="dark"] .img-dark { display: block !important; }
[data-theme="dark"] .img-light { display: none !important; }
.pilot { margin-top: auto; padding-top: 34px; font-family: var(--serif); font-style: italic; font-weight: 300; font-size: clamp(20px, 1.7vw, 25px); line-height: 1.3; letter-spacing: -.005em; }
/* The tile opens the case study; its two buttons sit above the link that covers the card */
.card-link { position: absolute; inset: 0; z-index: 3; border-radius: inherit; }
.card-link:focus-visible { outline: 2px solid var(--tone); outline-offset: -8px; }
/* The copy sits over the link but lets clicks fall through to it, except on the buttons */
:is(.t-snapshot, .t-jump) .card-copy { z-index: 4; pointer-events: none; }
.card-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 26px; pointer-events: auto; }
.card-btn { display: inline-flex; align-items: center; gap: 9px; height: 44px; padding: 0 19px; border-radius: 999px; font-size: 15px; font-weight: 400; white-space: nowrap;
  color: var(--ink-2); background: var(--glass-strong); border: 1px solid var(--glass-line); transition: box-shadow .5s var(--ease); }
.card-btn svg { width: 12px; height: 12px; flex: none; transition: transform .4s var(--ease); }
.card-btn.is-primary { color: var(--bg); background: var(--ink); border-color: transparent; box-shadow: 0 8px 22px rgba(10, 10, 10, .14); }
.card-btn.is-primary:hover { box-shadow: 0 14px 36px rgba(10, 10, 10, .22); }
.card-btn.is-primary:hover svg { transform: translateX(2px); }
.card-btn.is-soon { cursor: default; }
.card-btn.is-soon i { width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--tone); }

/* Heart Health: the hand lifts the iPad toward you on hover */
.t-heart { grid-column: span 7; }
.t-heart .card { min-height: 620px; }
/* The live mockup: the site's own recording plays on the iPad screen, warped to the screen's corners, with
   the hand and bezel layered in front. It's drawn at the photo's own size and scaled to fit the card. */
.t-heart .heart-live { position: absolute; width: 58%; right: 2%; bottom: -12%; aspect-ratio: 1300 / 1459; container-type: inline-size;
  transform-origin: 85% 95%; transition: transform 1.2s var(--ease); }
.heart-stage { position: absolute; left: 0; top: 0; width: 1300px; height: 1459px; transform-origin: 0 0; transform: scale(tan(atan2(100cqw, 1300px))); }
.heart-stage > * { position: absolute; left: 0; top: 0; max-width: none; }
.heart-base, .heart-front { width: 1300px; height: 1459px; }
.heart-base { filter: drop-shadow(0 110px 130px rgba(0, 40, 60, .28)); }
.heart-screen { width: 1074px; height: 798px; object-fit: fill; transform-origin: 0 0;
  transform: matrix3d(.8004473027, .4951110373, 0, -2.213186288e-06, -.5043599205, .8130808222, 0, -3.831731488e-06, 0, 0, 1, 0, 420.6205963, 16.46801333, 0, 1); }
.item.is-hot.t-heart .device { transform: translate3d(-3%, -9%, 0) rotate(-7deg); }

/* Brain Dump: the app's own screens */
.t-brain { grid-column: span 5; }
.t-brain .card { min-height: 620px; }
.t-brain .media { display: grid; place-items: end center; padding-top: 30px; }
.shots { position: relative; width: min(250px, 60%); aspect-ratio: 520 / 1077; margin-bottom: -70px; filter: drop-shadow(0 36px 50px rgba(50, 0, 110, .3)); }
.shots img { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; transform: translateY(10px) scale(.985); transition: opacity .9s var(--ease), transform 1.2s var(--ease); }
.shots img.is-on { opacity: 1; transform: none; }
.t-brain.is-listening .blob { animation: listen 1.6s var(--ease-io) infinite alternate; }
@keyframes listen { to { scale: 1.16; } }
.steps { display: flex; gap: 6px; margin-top: 18px; }
.steps i { width: 18px; height: 2px; border-radius: 2px; background: color-mix(in srgb, var(--ink) 16%, transparent); transition: background-color .6s var(--ease), width .6s var(--ease); }
.steps i.is-on { width: 30px; background: #8a3cff; }

/* Photo tiles */
.t-small { grid-column: span 4; }
.t-small .card { min-height: 500px; }
.t-small .media { margin: 26px 22px 22px; border-radius: var(--radius-sm); overflow: hidden; }
.t-small .media img { width: 100%; height: 100%; object-fit: cover; transform: scale(1.02); transition: transform 1.2s var(--ease); }
.item.is-hot.t-small .media img { transform: scale(1.06); }

/* ───────── About ───────── */
/* Below the fold: let the browser skip layout and paint until they get close */
.about, .contact { content-visibility: auto; contain-intrinsic-size: auto 900px; }
.about { max-width: 1380px; margin: 0 auto; padding: 100px var(--gutter) 30px; display: grid; grid-template-columns: 1fr 1fr; gap: 40px 60px; }
.about h2 { font-family: var(--serif); font-weight: 300; font-size: clamp(40px, 4.4vw, 66px); line-height: 1.05; letter-spacing: var(--track-heading); margin-top: 14px; text-wrap: balance; }
/* Where I work and study: each organisation's mark over the role, in the ink colour, marks sitting on one
   line and roles on the next. Hovering either brings up the organisation's own colours. */
.about-where { list-style: none; display: flex; flex-wrap: wrap; gap: 20px 56px; margin-top: 36px; }
.about-where li { display: grid; justify-items: start; gap: 12px; font-size: 15px; font-weight: 400; color: var(--ink-2); transition: color .4s var(--ease); }
.org-mark { position: relative; height: 42px; }
.org-mark::before, .org-mark::after { content: ""; position: absolute; inset: 0; transition: opacity .45s var(--ease); }
.org-mark::before { background: var(--ink); opacity: .72;
  -webkit-mask: var(--m) left bottom / contain no-repeat; mask: var(--m) left bottom / contain no-repeat; }
.org-mark::after { background: var(--c) left bottom / contain no-repeat; opacity: 0; }
.org-mark.is-influential { --m: url(../brand/influential.png); --c: url(../brand/influential-colour.png); width: 104px; }
.org-mark.is-ulster { --m: url(../brand/ulster-university.png); --c: url(../brand/ulster-university.png); width: 76px; }
[data-theme="dark"] .org-mark.is-influential { --c: url(../brand/influential-colour-dark.png); }
[data-theme="dark"] .org-mark.is-ulster::after { background: #fff; -webkit-mask: var(--m) left bottom / contain no-repeat; mask: var(--m) left bottom / contain no-repeat; }
@media (hover: hover) {
  .about-where li:hover { color: var(--ink); }
  .about-where li:hover .org-mark::before { opacity: 0; }
  .about-where li:hover .org-mark::after { opacity: 1; }
}
.about h2 em { font-style: italic; }
.about-body p { font-size: 18px; line-height: 1.6; color: var(--ink-2); max-width: 44ch; }
.about-body p + p { margin-top: 18px; }
.about-body em { font-style: italic; }

/* Toolkit: one row of monochrome marks that take their brand colour on hover */
.toolkit { grid-column: 1 / -1; margin-top: 56px; padding: 34px 6px 0; border-top: 1px solid var(--hair); display: flex; flex-wrap: wrap; align-items: flex-end; gap: 24px 50px; }
.toolkit-title { flex-basis: 100%; font-family: var(--serif); font-weight: 300; font-size: clamp(26px, 2.2vw, 32px); letter-spacing: -.012em; margin-bottom: 4px; }
.tool-group .label { display: block; margin-bottom: 14px; }
.tool-group ul { list-style: none; display: flex; gap: 24px; }
.tool { display: inline-flex; align-items: center; gap: 10px; font-size: 17px; font-weight: 400; color: var(--ink-2); white-space: nowrap; transition: color .4s var(--ease); }
.tool .mark { width: 20px; height: 20px; flex: none; background: currentColor; -webkit-mask-position: center; mask-position: center; -webkit-mask-size: contain; mask-size: contain; -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; transition: background-color .4s var(--ease); }
.tool:hover { color: var(--ink); }
.tool:hover .mark { background: var(--brand, currentColor); }

/* ───────── Contact ───────── */
.contact { position: relative; text-align: center; padding: 170px var(--gutter) 150px; overflow-x: clip; }
.contact h2 { font-family: var(--serif); font-weight: 300; font-size: clamp(64px, 10vw, 150px); line-height: .95; letter-spacing: var(--track-display); word-spacing: var(--word-display); }
.contact h2 em { font-style: italic; }
.contact .sub { margin-top: 20px; font-size: 18px; color: var(--ink-2); }
/* One clear action: email. Copy sits beside it; LinkedIn is a quiet link underneath. */
.cta { display: inline-flex; align-items: center; gap: 10px; margin-top: 40px; }
.email { position: relative; display: inline-flex; align-items: center; gap: 12px; padding: 19px 30px 19px 26px; border-radius: 999px;
  font-size: clamp(17px, 1.5vw, 21px); font-weight: 400; letter-spacing: -.01em; color: var(--bg); background: var(--ink);
  box-shadow: 0 8px 22px rgba(10, 10, 10, .16); will-change: transform;
  transition: box-shadow .6s var(--ease), background-color .6s var(--ease), color .6s var(--ease); }
.email:hover { box-shadow: 0 16px 44px rgba(10, 10, 10, .26); }
@property --sweep { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
.email::before { content: ""; position: absolute; inset: -3px; border-radius: 999px; padding: 2px; opacity: 0; pointer-events: none;
  background: conic-gradient(from var(--sweep), #ed1652, #ff6a1a, #ffb22c, #43d9ff, #8a3cff, #3a17e0, #ed1652);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask-composite: exclude; }
.cta.in .email::before { animation: sweep 1.8s var(--ease-io) .5s both; }
.cta.in .email:hover::before { animation: orbit 2.6s linear infinite; opacity: .95; }
@keyframes sweep { 0% { opacity: 0; --sweep: 0deg; } 25% { opacity: 1; } 100% { opacity: 0; --sweep: 360deg; } }
@keyframes orbit { to { --sweep: 360deg; } }
[data-theme="dark"] .email { box-shadow: 0 10px 30px rgba(0, 0, 0, .55); }
[data-theme="dark"] .email:hover { box-shadow: 0 16px 44px rgba(0, 0, 0, .7); }
.email-icon { width: 18px; height: 18px; flex: none; }
.copy { display: inline-flex; align-items: center; gap: 8px; height: 62px; padding: 0 22px 0 20px; border-radius: 999px; font-size: 14px; font-weight: 400; color: var(--ink-2);
  background: var(--glass-strong); border: 1px solid var(--glass-line); transition: color .3s var(--ease), border-color .3s var(--ease); }
.copy:hover { color: var(--ink); border-color: color-mix(in srgb, var(--ink) 18%, transparent); }
.copy svg { width: 16px; height: 16px; flex: none; }
.copy.is-copied { color: var(--ink); }
.linkedin { display: inline-flex; align-items: center; gap: 9px; margin-top: 28px; font-size: 15px; font-weight: 400; color: var(--ink-2); transition: color .3s var(--ease); }
.linkedin .mark { width: 16px; height: 16px; flex: none; background: currentColor; -webkit-mask-size: contain; mask-size: contain; -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; -webkit-mask-position: center; mask-position: center; }
.linkedin .arr { width: 11px; height: 11px; transition: transform .4s var(--ease); }
.linkedin:hover { color: var(--ink); }
.linkedin:hover .arr { transform: translate(2px, -2px); }
.contact .linkedin { display: flex; width: max-content; margin-left: auto; margin-right: auto; }
.contact-glow { position: absolute; z-index: -1; left: 50%; top: 58%; width: min(900px, 110vw); aspect-ratio: 2.2; translate: -50% -50%; pointer-events: none; opacity: .35; filter: blur(60px);
  background: radial-gradient(closest-side, var(--p2), transparent), radial-gradient(closest-side at 30% 60%, var(--p5), transparent 70%), radial-gradient(closest-side at 72% 40%, var(--p4), transparent 70%);
  mix-blend-mode: var(--bleed-blend); }

footer { max-width: 1380px; margin: 0 auto; padding: 26px var(--gutter) 34px; display: flex; justify-content: space-between; gap: 20px; font-size: 13px; font-weight: 400; color: var(--whisper); border-top: 1px solid var(--hair); }
footer nav { display: flex; gap: 22px; }
footer a:hover { color: var(--ink); }

/* ───────── Reveal ───────── */
.js .reveal { opacity: 0; translate: 0 30px; transition: opacity 1s var(--ease), translate 1.1s var(--ease); transition-delay: var(--d, 0s); }
.js .reveal.in { opacity: 1; translate: 0 0; }

/* ───────── Responsive ───────── */
@media (max-width: 1180px) {
  .toolkit > .label { flex-basis: 100%; }
}
@media (max-width: 1040px) {
  .t-snapshot .card, .t-jump .card { grid-template-columns: 1fr; min-height: 0; }
  .t-snapshot .media { min-height: 560px; }
  .t-snapshot .device { height: 520px; }
  .t-jump .media { grid-column: 1; grid-row: 3; min-height: 440px; }
  .t-jump .card-top { grid-column: 1; grid-row: 1; padding: 36px 44px 0; }
  .t-jump .card-copy { grid-column: 1; grid-row: 2; padding: 22px 44px 10px; }
  .t-jump .media { grid-row: 3; }
  .t-heart, .t-brain { grid-column: span 12; }
  .t-small { grid-column: span 6; }
  .about { grid-template-columns: 1fr; }
}
@media (max-width: 700px) {
  :root { --radius: 38px; --radius-sm: 26px; }
  .links { gap: 16px; }
  .links a:nth-child(2) { display: none; }
  .eclipse { left: -40vw; width: 180vw; top: 70%; }
  .hero-copy { top: 38%; }
  .hero .intro { font-size: 16px; }
  .t-snapshot .card-top, .t-jump .card-top { padding: 28px 28px 0; }
  .t-snapshot .card-copy { padding: 20px 28px 30px; }
  .t-jump .card-copy { padding: 20px 28px 10px; }
  .card-top { padding: 26px 26px 0; }
  .card-copy { padding: 14px 26px 0; }
  .stats { grid-template-columns: 1fr 1fr; gap: 26px; }
  .t-small { grid-column: span 12; }
  .t-heart .card { min-height: 560px; }
  .t-heart .heart-live { width: 88%; right: -10%; bottom: -10%; }
  .t-jump .media { min-height: 320px; }
  .tool-group ul { flex-wrap: wrap; gap: 10px 20px; }
  .contact { padding: 120px var(--gutter) 110px; }
  .cta { flex-direction: column; }
  .email { padding: 17px 24px 17px 22px; }
  .copy { height: 48px; }
  footer { flex-direction: column; gap: 10px; }
}
@media (prefers-reduced-motion: reduce) {
  .cta.in .email::before, .cta.in .email:hover::before { animation: none; opacity: 0; }
  .scene { height: auto; }
  .hero { position: relative; }
  .corona, .live::before { animation: none; }
  .js .reveal { opacity: 1; translate: none; transition: none; }
  ::view-transition-new(root) { animation: none; }
}
