/* ═══════════════════════════════════════════════════════════════
   XODE — CANVAS

   The site's look since the Canvas redesign: pure white, near-black
   type, black pill buttons, Inter Tight headlines, and one motion
   language on every public page.

   A LAYER, NOT A REWRITE. theme-light.css already turns every public
   page light through the tokens, and the Canvas palette sits there with
   the others. The boot snippet in each page's <head> sets
   data-theme="light" data-light="canvas" before the first paint. What
   is here is what a palette cannot say — type, shape, the bar at the
   top, and movement. No markup changes and no behaviour changes.

   Every rule is scoped to :root[data-light="canvas"], so the admin
   console and the editors, which never carry that attribute, are left
   exactly as they were.
   ═══════════════════════════════════════════════════════════════ */

/* ── TYPE ─────────────────────────────────────────────────────── */
:root[data-light="canvas"] :is(.hero-headline, .sec-title, .pg-title, .gw-title, .about-hero-title, .pg-cta h2) {
  font-family: 'Inter Tight', 'Inter', sans-serif;
  letter-spacing: -.04em;
  /* Tight letters pull the gaps between words in with them; at display
     sizes "It got a lot" ran together into one word. */
  word-spacing: .06em;
}
:root[data-light="canvas"] :is(.sec-title, .pg-title, .gw-title, .about-hero-title) {
  font-weight: 800;
  color: var(--text-0);
}

:root[data-light="canvas"] .eyebrow {
  font-family: var(--font-body);
  font-weight: 700;
  letter-spacing: .14em;
  color: var(--violet-ink);
}
:root[data-light="canvas"] .eyebrow::before { background: var(--violet-ink); }

:root[data-light="canvas"] ::selection { background: #C9F26B; color: #0B0B0F; }

/* ── BUTTONS ──────────────────────────────────────────────────────
   Black pills. The sheen is a background-image rather than a pseudo
   element: some buttons already use ::before/::after or hold a badge
   that overflow:hidden would clip. */
:root[data-light="canvas"] .btn-primary {
  background-color: #0B0B0F;
  background-image: linear-gradient(105deg, transparent 42%, rgba(255, 255, 255, .26) 50%, transparent 58%);
  background-size: 260% 100%;
  background-position: 140% 0;
  background-repeat: no-repeat;
  color: #FFFFFF;
  /* The old violet hairline round the button read as a focus ring on
     black; the border stays (so no button changes size), unseen. */
  border-color: #0B0B0F;
  border-radius: 999px;
  box-shadow: 0 10px 24px -14px rgba(109, 74, 255, .48);
  transition: background-position .75s cubic-bezier(.22, 1, .36, 1), background-color .2s,
              transform .2s cubic-bezier(.22, 1, .36, 1), box-shadow .2s;
}
:root[data-light="canvas"] .btn-primary:hover {
  background-color: #1D1D26;
  background-position: -40% 0;
  box-shadow: 0 16px 34px -16px rgba(109, 74, 255, .48);
  transform: translateY(-2px);
}
:root[data-light="canvas"] .btn-primary:active { transform: translateY(0) scale(.97); }
:root[data-light="canvas"] :is(.btn-primary, .btn-ghost):focus-visible {
  outline: 3px solid rgba(109, 74, 255, .45);
  outline-offset: 3px;
}

:root[data-light="canvas"] .btn-ghost {
  border-radius: 999px;
  border: 1.5px solid #D6D6DE;
  background: #FFFFFF;
  color: #0B0B0F;
  transition: border-color .2s, background .2s, transform .2s cubic-bezier(.22, 1, .36, 1);
}
:root[data-light="canvas"] .btn-ghost:hover {
  border-color: #0B0B0F;
  background: #FFFFFF;
  transform: translateY(-2px);
}
:root[data-light="canvas"] .btn-ghost:active { transform: scale(.97); }
:root[data-light="canvas"] .btn-amber { border-radius: 999px; }

/* ── THE BAR AT THE TOP ───────────────────────────────────────────
   White and frosted. Once the page scrolls it slims, gains a hairline
   and a soft shadow (site-motion.js adds .is-scrolled). It keeps a
   view-transition name of its own, so it stays put while the page
   beneath it changes. */
:root[data-light="canvas"] .nav {
  background: rgba(255, 255, 255, .82);
  border-bottom-color: transparent;
  view-transition-name: xode-nav;
  transition: background-color .3s, border-color .3s, box-shadow .3s;
}
:root[data-light="canvas"] .nav.is-scrolled {
  background: rgba(255, 255, 255, .74);
  border-bottom-color: var(--border-1);
  box-shadow: 0 12px 32px -24px rgba(109, 74, 255, .45);
}
:root[data-light="canvas"] .nav-inner { transition: height .35s cubic-bezier(.22, 1, .36, 1); }
:root[data-light="canvas"] .nav.is-scrolled .nav-inner { height: 58px; }
:root[data-light="canvas"] .nav-link { color: var(--text-1); transition: color .15s; }
:root[data-light="canvas"] .nav-link:hover { color: var(--text-0); }
:root[data-light="canvas"] .nav-link.active { background: transparent; color: var(--text-0); }
:root[data-light="canvas"] .nav-link.active::after { background: #0B0B0F; }

/* ── THE SIGN-IN CARD ─────────────────────────────────────────────
   auth.js paints it dark with its own style tag; on a white page it
   read as a stray window. Same card, same buttons, Canvas colours. */
:root[data-light="canvas"] .xlp-wrap {
  background: #FFFFFF;
  border-color: #E6E6EC;
  box-shadow: 0 24px 60px -24px rgba(109, 74, 255, .35), 0 2px 8px rgba(109, 74, 255, .06);
}
:root[data-light="canvas"] :is(.xlp-title, .xlp-signed-name) { color: #0B0B0F; }
:root[data-light="canvas"] :is(.xlp-sub, .xlp-signed-email, .xlp-usage-row) { color: #6B6B78; }
:root[data-light="canvas"] :is(.xlp-hint, .xlp-footer-note) { color: #8A8A96; }
:root[data-light="canvas"] .xlp-logo { background: #F2F2F6; }
:root[data-light="canvas"] .xlp-close { color: #8A8A96; }
:root[data-light="canvas"] .xlp-close:hover { background: #F2F2F6; color: #0B0B0F; }
:root[data-light="canvas"] .xlp-divider { background: #ECECF1; }
:root[data-light="canvas"] .xlp-bar-track { background: #ECECF1; }
:root[data-light="canvas"] .xlp-action-btn.primary { background: #0B0B0F; }
:root[data-light="canvas"] .xlp-action-btn.primary:hover { background: #1D1D26; }
:root[data-light="canvas"] .xlp-action-btn.ghost { background: #FFFFFF; color: #0B0B0F; border-color: #D6D6DE; }
:root[data-light="canvas"] .xlp-action-btn.ghost:hover { background: #FFFFFF; border-color: #0B0B0F; }

/* ── PROFESSION CARDS ─────────────────────────────────────────────
   No blueprint grid on white; a clean tint instead. Eight distinct
   colours — the old set repeated orange and two near-identical golds —
   carried through the wash, border, icon, wireframe and hover glow.
   background-size is restated: the base rule sizes three layers, and a
   two-layer list would inherit its 24px tile. */
:root[data-light="canvas"] .prof-card.p-developer    { --accent: #6D4AFF; }
:root[data-light="canvas"] .prof-card.p-designer     { --accent: #D946EF; }
:root[data-light="canvas"] .prof-card.p-photographer { --accent: #EAB308; }
:root[data-light="canvas"] .prof-card.p-doctor       { --accent: #14B8A6; }
:root[data-light="canvas"] .prof-card.p-creator      { --accent: #F43F5E; }
:root[data-light="canvas"] .prof-card.p-writer       { --accent: #0EA5E9; }
:root[data-light="canvas"] .prof-card.p-student      { --accent: #22C55E; }
:root[data-light="canvas"] .prof-card.p-business     { --accent: #F97316; }
:root[data-light="canvas"] .prof-card {
  background-color: #FFFFFF;
  background-image:
    radial-gradient(120% 90% at 100% 0%, color-mix(in srgb, var(--accent) 17%, transparent), transparent 62%),
    linear-gradient(180deg, #FFFFFF 45%, color-mix(in srgb, var(--accent) 7%, #FFFFFF) 100%);
  background-size: 100% 100%, 100% 100%;
  border-color: color-mix(in srgb, var(--accent) 24%, #EAEAF0);
  border-radius: 22px;
  box-shadow: 0 10px 28px -22px color-mix(in srgb, var(--accent) 50%, transparent);
}
:root[data-light="canvas"] .prof-card:hover {
  border-color: color-mix(in srgb, var(--accent) 48%, #EAEAF0);
  box-shadow: 0 22px 44px -24px color-mix(in srgb, var(--accent) 58%, transparent);
}
:root[data-light="canvas"] .prof-card::after { height: 3px; }
:root[data-light="canvas"] .prof-card .prof-icon svg { stroke: color-mix(in srgb, var(--accent) 82%, #0B0B0F); }
/* The dark theme turned the name white on hover — on a white card that
   made it vanish. */
:root[data-light="canvas"] .prof-card:hover .prof-name { color: var(--text-0); }

/* ── EVERY PAGE'S HERO, IN THE HOME PAGE'S STYLE ──────────────────
   Centred, one big Inter Tight headline, the coloured word marked with
   the lime highlighter instead of the gradient, the eyebrow as a pill,
   and popups — stickers and two cursors — round the title
   (site-motion.js adds those). Covers the six hero shapes the pages
   use; the home hero (#hero) keeps its own rules. Markup, ids and every
   button are untouched. */
:root[data-light="canvas"] :is(.pg-hero .pg-eyebrow, .about-hero .eyebrow, .contact-hero .eyebrow, .gw-hero .eyebrow, .account-hero .eyebrow, .hero:not(#hero) .hero-badge) {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 18px; border: 0; border-radius: 999px;
  background: #F3F0FF; color: #34247F;
  font: 600 13.5px/1.2 Inter, sans-serif; letter-spacing: .03em; text-transform: none;
}
:root[data-light="canvas"] :is(.pg-hero .pg-eyebrow, .about-hero .eyebrow, .contact-hero .eyebrow, .gw-hero .eyebrow, .account-hero .eyebrow)::before {
  content: ''; display: block; width: 6px; height: 6px; margin: 0; border-radius: 50%; background: #6D4AFF;
}
:root[data-light="canvas"] .hero:not(#hero) .hero-dot { background: #6D4AFF; }

:root[data-light="canvas"] :is(.pg-hero .pg-title, .about-hero-title, .contact-hero h1, .gw-hero .gw-title, .account-hero h1, .hero:not(#hero) .hero-headline) {
  font-family: 'Inter Tight', 'Inter', sans-serif !important;
  font-size: clamp(44px, 7.2vw, 104px) !important;
  font-weight: 800 !important;
  line-height: .95 !important;
  letter-spacing: -.045em !important;
  word-spacing: .06em;
  color: var(--text-0) !important;
  margin: 26px 0 28px !important;
  text-wrap: balance;
}
/* The highlighter: a band behind the lower half of the word, which wraps
   with the text on two lines where an inline-block would not. */
:root[data-light="canvas"] :is(.pg-hero .pg-title em, .about-hero-title .grad-text, .contact-hero h1 .grad-text, .gw-hero .gw-title .grad-text, .account-hero h1 .grad-text, .hero:not(#hero) .hero-headline .grad-text) {
  font-style: normal;
  color: var(--text-0);
  -webkit-text-fill-color: currentColor;
  background: linear-gradient(transparent 56%, #C9F26B 56%, #C9F26B 90%, transparent 90%) no-repeat 0 0 / 100% 100%;
  -webkit-background-clip: border-box; background-clip: border-box;
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
  padding: 0 .05em;
  animation: none;
}
:root[data-light="canvas"] :is(.pg-sub, .about-hero-sub, .contact-hero .caption, .gw-hero .gw-sub, .account-hero .caption, .hero:not(#hero) .hero-sub) {
  max-width: 760px !important; margin-left: auto !important; margin-right: auto !important;
  font-size: clamp(16.5px, 1.45vw, 21px) !important; line-height: 1.58 !important;
  color: var(--text-2) !important;
  /* Contact and account set theirs in the caption face, bold italic;
     at this size that shouted. Body type, like the home page. */
  font-family: var(--font-body, 'Inter'), sans-serif !important;
  font-style: normal !important; font-weight: 400 !important; letter-spacing: 0 !important;
}
:root[data-light="canvas"] .pg-hero::after { display: none; }
/* The account hero was the one left-aligned title block; centred like
   the rest so the popups sit beside it rather than on it. */
:root[data-light="canvas"] :is(.account-hero, .contact-hero) .container { text-align: center; }
/* The rule under the contact hero — Canvas separates with space. */
:root[data-light="canvas"] .contact-hero::after { display: none; }
/* 720px made "The Great Wall of XODE" three lines at this size. The
   column widens for the title; the lines under it keep a reading width. */
:root[data-light="canvas"] .gw-hero .gw-hero-inner { max-width: 1000px; }
:root[data-light="canvas"] .gw-hero .gw-cap { max-width: 720px; margin-left: auto; margin-right: auto; }
:root[data-light="canvas"] .gw-hero .gw-search { max-width: 560px; margin-left: auto; margin-right: auto; }

/* The three product pages had a two-column hero; like the home page, the
   copy is centred and the picture follows beneath it. */
:root[data-light="canvas"] .hero:not(#hero) .hero-inner {
  grid-template-columns: 1fr; justify-items: center; text-align: center; gap: clamp(44px, 5vw, 72px);
}
:root[data-light="canvas"] .hero:not(#hero) .hero-inner > div:first-child {
  position: relative; width: 100%; display: flex; flex-direction: column; align-items: center;
}
:root[data-light="canvas"] .hero:not(#hero) .hero-caption { text-align: center; margin-bottom: 30px; }
:root[data-light="canvas"] .hero:not(#hero) .hero-actions { justify-content: center; margin-bottom: 0; }
:root[data-light="canvas"] .hero:not(#hero) .hero-stats {
  justify-content: center; gap: clamp(28px, 5vw, 76px); margin-top: 34px; padding-top: 0; border-top: 0;
}
:root[data-light="canvas"] .hero:not(#hero) .stat-num {
  background: none; -webkit-text-fill-color: currentColor; color: var(--text-0);
  font-family: 'Inter Tight', 'Inter', sans-serif; font-weight: 800;
  font-size: clamp(30px, 3.4vw, 50px); letter-spacing: -.045em;
}
:root[data-light="canvas"] .hero:not(#hero) .stat-lbl { color: var(--text-3); font-size: 13px; }
:root[data-light="canvas"] .hero:not(#hero) .hero-visual { width: min(880px, 100%); text-align: left; }

/* The popups. A zero-height layer just above the title, as wide as the
   page's content, so they sit beside the headline on any hero. */
:root[data-light="canvas"] .xm-pops {
  --pw: min(1240px, calc(100vw - 150px));
  position: relative; z-index: 3; display: block; height: 0; width: var(--pw);
  margin-left: calc(50% - var(--pw) / 2); align-self: flex-start;
  pointer-events: none; text-align: left;
}
.xm-pop { position: absolute; }
.xm-pop.p1 { left: 0; top: 40px; transform: rotate(-8deg); }
.xm-pop.p2 { right: 0; top: 8px; transform: rotate(7deg); }
.xm-pop.p3 { right: 8%; top: 182px; }
.xm-pop.p4 { left: 7%; top: 214px; }
/* The account hero is one short line and clips what hangs below it. */
.account-hero .xm-pop.p3 { top: 118px; }
.account-hero .xm-pop.p4 { top: 140px; }
.xm-sticker {
  padding: 10px 15px; border-radius: 14px; color: #0B0B0F;
  font: 700 15px/1.2 Inter, sans-serif; white-space: nowrap;
  box-shadow: 0 16px 34px -14px rgba(109, 74, 255, .21);
}
.xm-sticker.mono { font-family: 'JetBrains Mono', ui-monospace, monospace; font-weight: 500; }
.xm-cursor { display: flex; align-items: flex-start; }
.xm-cursor svg { width: 22px; height: 22px; filter: drop-shadow(0 2px 3px rgba(109, 74, 255, .14)); }
.xm-cursor span {
  margin: 16px 0 0 -3px; padding: 5px 10px; border-radius: 99px;
  background: var(--cc); color: #FFFFFF; font: 650 12.5px/1 Inter, sans-serif;
  white-space: nowrap; box-shadow: 0 6px 14px -6px rgba(109, 74, 255, .21);
}
@media (max-width: 1180px) { :root[data-light="canvas"] .xm-pops { display: none; } }

@media (prefers-reduced-motion: no-preference) {
  :root.xm-ready .xm-pop { animation: xm-pop .8s cubic-bezier(.22, 1.3, .36, 1) backwards, xm-float 6.5s ease-in-out infinite; }
  :root.xm-ready .xm-pop.p1 { animation-delay: .35s, 0s; }
  :root.xm-ready .xm-pop.p2 { animation-delay: .5s, -2.5s; animation-duration: .8s, 7.5s; }
  :root.xm-ready .xm-pop.p3 { animation-delay: .7s, -1s; animation-duration: .8s, 8s; }
  :root.xm-ready .xm-pop.p4 { animation-delay: .85s, -3.5s; }
  :root.xm-ready[data-light="canvas"] :is(.pg-hero .pg-title em, .about-hero-title .grad-text, .contact-hero h1 .grad-text, .gw-hero .gw-title .grad-text, .account-hero h1 .grad-text, .hero:not(#hero) .hero-headline .grad-text) {
    animation: xm-mark 1s cubic-bezier(.22, 1, .36, 1) .55s backwards;
  }
}
@keyframes xm-pop   { from { opacity: 0; scale: .5; } }
@keyframes xm-float { 0%, 100% { translate: 0 0; } 50% { translate: 0 -8px; } }
@keyframes xm-mark  { from { background-size: 0% 100%; } }

/* ── THE GREAT WALL: ROOM TO BREATHE, AND A NEW BACKGROUND ─────────
   Its sections had no padding at desktop width at all (shared.css only
   pads them inside phone and tablet queries), so every wall's heading
   sat on the cards above it. Same rhythm as the home page now, bigger
   section titles, and a clear gap between a heading and its row.

   The rows of hung frames behind the page are switched off here (the
   markup and tools/build-great-wall.js stay, and the dark theme still
   draws them); site-motion.js fills the same fixed layer with drifting
   colour and shapes that come and go at random. */
:root[data-light="canvas"] .gw-hero ~ section {
  padding-top: clamp(72px, 8vw, 120px);
  padding-bottom: clamp(72px, 8vw, 120px);
}
:root[data-light="canvas"] .gw-hero ~ section .sec-title {
  font-size: clamp(34px, 4.4vw, 64px); line-height: 1.02;
}
:root[data-light="canvas"] .gw-hero ~ section :is(.section-header, .section-header-row) { margin-bottom: clamp(34px, 3.4vw, 54px); }
:root[data-light="canvas"] .gw-hero ~ section .sec-title + :is(p, .sec-sub, .sec-caption) { margin-top: 20px; }
:root[data-light="canvas"] .gw-hero ~ section .eyebrow { margin-bottom: 16px; }
/* The alternate bands let the colour behind them show through a little. */
:root[data-light="canvas"] .gw-hero ~ .section-alt { background: rgba(247, 247, 250, .62); }

:root[data-light="canvas"] .gw-wall { background: none; }
:root[data-light="canvas"] .gw-wall i,
:root[data-light="canvas"] .gw-wall::after { display: none; }
.gw-field { position: absolute; inset: 0; overflow: hidden; }
.gw-orb {
  position: absolute; left: 0; top: 0; border-radius: 50%;
  translate: -50% -50%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--oc) 34%, transparent), transparent 72%);
  filter: blur(10px);
  transition-property: transform, opacity;
  transition-timing-function: cubic-bezier(.45, 0, .25, 1), ease-in-out;
  will-change: transform, opacity;
}
.gw-spark {
  position: absolute; width: var(--sz, 14px); height: var(--sz, 14px);
  translate: -50% -50%; pointer-events: none;
  animation: gw-spark 4.5s cubic-bezier(.22, 1, .36, 1) both;
}
.gw-spark.dot    { border-radius: 50%; background: var(--sc); }
.gw-spark.ring   { border-radius: 50%; border: 2px solid var(--sc); }
.gw-spark.square { border-radius: 4px; border: 2px solid var(--sc); }
.gw-spark.spark  { background: var(--sc); clip-path: polygon(50% 0, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0 50%, 39% 39%); }
.gw-spark.plus::before,
.gw-spark.plus::after { content: ''; position: absolute; left: 50%; top: 50%; translate: -50% -50%; border-radius: 2px; background: var(--sc); }
.gw-spark.plus::before { width: 100%; height: 2.5px; }
.gw-spark.plus::after  { width: 2.5px; height: 100%; }
@keyframes gw-spark {
  0%   { opacity: 0;   transform: translate(0, 0) rotate(0deg) scale(.3); }
  22%  { opacity: .8;  transform: translate(calc(var(--dx) * .25), calc(var(--dy) * .25)) rotate(calc(var(--rot) * .3)) scale(1); }
  70%  { opacity: .55; }
  100% { opacity: 0;   transform: translate(var(--dx), var(--dy)) rotate(var(--rot)) scale(.6); }
}
@media (prefers-reduced-motion: reduce) {
  .gw-orb { transition: none; }
  .gw-spark { display: none; }
}

/* ── THE "INAPPROPRIATE LANGUAGE" POPUP AND TOAST ──────────────────
   moderation.js paints them dark with its own style tag. On a white
   page: a white card over a see-through, softly blurred backdrop, so
   the form it is about stays visible behind it. */
:root[data-light="canvas"] .mod-scrim {
  background: rgba(11, 11, 15, .22);
  -webkit-backdrop-filter: blur(8px) saturate(1.1);
  backdrop-filter: blur(8px) saturate(1.1);
}
:root[data-light="canvas"] .mod-card {
  background: rgba(255, 255, 255, .96);
  border: 1px solid #ECECF1;
  border-radius: 24px;
  box-shadow: 0 40px 90px -36px rgba(109, 74, 255, .45), 0 2px 8px rgba(109, 74, 255, .06);
}
:root[data-light="canvas"] .mod-card.severe { border-color: rgba(194, 53, 47, .35); }
:root[data-light="canvas"] .mod-icon { background: #FFF4E2; border-color: rgba(255, 180, 84, .45); }
:root[data-light="canvas"] .mod-card.severe .mod-icon { background: #FDECEB; border-color: rgba(194, 53, 47, .3); }
:root[data-light="canvas"] .mod-title { font-family: 'Inter Tight', 'Inter', sans-serif; font-weight: 800; color: #0B0B0F; }
:root[data-light="canvas"] .mod-text { color: #55555F; }
:root[data-light="canvas"] .mod-text strong { color: #0B0B0F; }
:root[data-light="canvas"] .mod-quote { background: #F7F7FA; border-color: #ECECF1; color: #C2352F; }
:root[data-light="canvas"] .mod-policy { background: #FFF8EC; border-color: rgba(255, 180, 84, .4); color: #6B5A3A; }
:root[data-light="canvas"] .mod-policy b { color: #C2352F; }
:root[data-light="canvas"] .mod-ref { color: #8A8A96; }
:root[data-light="canvas"] .mod-btn { border-radius: 999px; }
:root[data-light="canvas"] .mod-btn.primary { background: #0B0B0F; color: #FFFFFF; }
:root[data-light="canvas"] .mod-btn.primary:hover { background: #1D1D26; }
:root[data-light="canvas"] .mod-btn.ghost { background: #FFFFFF; border: 1.5px solid #D6D6DE; color: #0B0B0F; }
:root[data-light="canvas"] .mod-btn.ghost:hover { background: #FFFFFF; border-color: #0B0B0F; }
:root[data-light="canvas"] .mod-toast {
  background: rgba(255, 255, 255, .94);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 180, 84, .6);
  color: #0B0B0F;
  box-shadow: 0 16px 40px -18px rgba(109, 74, 255, .45);
}

/* ── THE OPEN EDITOR MENU ("What are you making?") ─────────────────
   shared.css draws it near-black. On Canvas pages: a white card over a
   see-through blurred backdrop, three softly tinted choice cards, and
   the little drawings recoloured for a light ground. */
:root[data-light="canvas"] .em-scrim {
  background: rgba(11, 11, 15, .22);
  -webkit-backdrop-filter: blur(10px) saturate(1.1);
  backdrop-filter: blur(10px) saturate(1.1);
}
:root[data-light="canvas"] .em {
  background: #FFFFFF;
  border-color: #ECECF1;
  border-radius: 30px;
  box-shadow: 0 50px 110px -40px rgba(109, 74, 255, .45), 0 2px 8px rgba(109, 74, 255, .06);
}
:root[data-light="canvas"] .em h2 { font-family: 'Inter Tight', 'Inter', sans-serif; font-size: clamp(26px, 3.6vw, 38px); letter-spacing: -.035em; color: #0B0B0F; }
:root[data-light="canvas"] .em-sub { color: #55555F; }
:root[data-light="canvas"] .em-x { color: #6B6B78; }
:root[data-light="canvas"] .em-x:hover { background: #F2F2F6; color: #0B0B0F; }
:root[data-light="canvas"] .em-card {
  border-color: #ECECF1;
  border-radius: 22px;
  background: #FFFFFF;
}
:root[data-light="canvas"] .em-website   { background: linear-gradient(180deg, #F6F3FF 0%, #FFFFFF 62%); }
:root[data-light="canvas"] .em-portfolio { background: linear-gradient(180deg, #FFF6E8 0%, #FFFFFF 62%); }
:root[data-light="canvas"] .em-resume    { background: linear-gradient(180deg, #EAF8F4 0%, #FFFFFF 62%); }
:root[data-light="canvas"] .em-card:hover,
:root[data-light="canvas"] .em-card:focus-visible { box-shadow: 0 24px 50px -24px rgba(109, 74, 255, .45); }
:root[data-light="canvas"] .em-website:hover,   :root[data-light="canvas"] .em-website:focus-visible   { background: linear-gradient(180deg, #EFEAFF 0%, #FFFFFF 70%); border-color: #6D4AFF; }
:root[data-light="canvas"] .em-portfolio:hover, :root[data-light="canvas"] .em-portfolio:focus-visible { background: linear-gradient(180deg, #FFEFD6 0%, #FFFFFF 70%); border-color: #F59E0B; }
:root[data-light="canvas"] .em-resume:hover,    :root[data-light="canvas"] .em-resume:focus-visible    { background: linear-gradient(180deg, #DDF4EE 0%, #FFFFFF 70%); border-color: #14B8A6; }
:root[data-light="canvas"] .em-website   .em-badge { background: #EEE9FF; color: #4B32C3; }
:root[data-light="canvas"] .em-portfolio .em-badge { background: #FFEBCC; color: #8A5200; }
:root[data-light="canvas"] .em-resume    .em-badge { background: #D6F3EC; color: #0F766E; }
:root[data-light="canvas"] .em-art { background: rgba(255, 255, 255, .7); border-color: rgba(11, 11, 15, .06); }
:root[data-light="canvas"] .em-art svg rect[fill="#1C1C24"] { fill: #FFFFFF; }
:root[data-light="canvas"] .em-art svg [stroke="#3A3A46"] { stroke: #D9D4EE; }
:root[data-light="canvas"] .em-art svg rect[fill="#5A5A68"] { fill: #C9C4DC; }
:root[data-light="canvas"] .em-art svg rect[fill="#2A2A34"] { fill: #FFE3B8; }
:root[data-light="canvas"] .em-art svg rect[fill="#E7E7EA"] { fill: #5B4A2E; }
:root[data-light="canvas"] .em-art svg rect[fill="#F3F3F1"] { fill: #FFFFFF; }
:root[data-light="canvas"] .em-label { color: #0B0B0F; }
:root[data-light="canvas"] .em-blurb { color: #55555F; }
:root[data-light="canvas"] .em-learn { border-top-color: #ECECF1; color: #6B6B78; }
:root[data-light="canvas"] .em-learn:hover { color: #0B0B0F; }

/* ── SURFACES ─────────────────────────────────────────────────── */
:root[data-light="canvas"] .section-alt { background: var(--bg-1); border-block-color: transparent; }
/* Canvas separates sections with space, not rules. */
:root[data-light="canvas"] hr.grad-line { display: none; }
:root[data-light="canvas"] footer { background: var(--bg-0); }
/* The coloured glows behind a landing hero were painted for a dark
   page; on white they read as a haze. */
:root[data-light="canvas"] .hero::before,
:root[data-light="canvas"] .hero::after { opacity: .45; }

/* ═══════════════════════════════════════════════════════════════
   MOTION

   Eight patterns, one language, on every public page:
     1. pages cross-fade and rise into place (View Transitions)
     2. a page's title block arrives in a short stagger
     3. sections below the fold rise in as they are reached
     4. cards in a grid follow their section, one after another
     5. buttons lift, sheen and press
     6. the bar slims and frosts on scroll
   (the home page adds the board demo, the hero stickers and the
    highlight sweep in its own style block)

   Fill mode is `backwards`, never `both`: a forwards fill would hold
   transform after the animation and quietly disable every hover lift
   on the page.

   Everything is off under prefers-reduced-motion, and the boot snippet
   only sets .xm-ready when motion is welcome.
   ═══════════════════════════════════════════════════════════════ */

@view-transition { navigation: auto; }

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}

@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) { animation: xm-leave .26s cubic-bezier(.4, 0, 1, 1) both; }
  ::view-transition-new(root) { animation: xm-enter .48s cubic-bezier(.22, 1, .36, 1) both; }

  /* 2 — the title block of a page. */
  :root.xm-ready[data-light="canvas"] :is(.pg-hero, .gw-hero, .about-hero, .account-hero, .contact-hero) .container > *,
  :root.xm-ready[data-light="canvas"] .hero .hero-inner > * {
    animation: xm-rise .9s cubic-bezier(.22, 1, .36, 1) backwards;
  }
  :root.xm-ready[data-light="canvas"] :is(.pg-hero, .gw-hero, .about-hero, .account-hero, .contact-hero) .container > :nth-child(2),
  :root.xm-ready[data-light="canvas"] .hero .hero-inner > :nth-child(2) { animation-delay: 110ms; }
  :root.xm-ready[data-light="canvas"] :is(.pg-hero, .gw-hero, .about-hero, .account-hero, .contact-hero) .container > :nth-child(3) { animation-delay: 200ms; }
  :root.xm-ready[data-light="canvas"] :is(.pg-hero, .gw-hero, .about-hero, .account-hero, .contact-hero) .container > :nth-child(n+4) { animation-delay: 280ms; }

  /* 3 and 4 — sections and their cards. site-motion.js adds .xm-sec
     only to sections that start below the fold, so nothing on screen
     at load ever blinks out; it removes the classes once the section
     has arrived, handing every card its own hover back. */
  :root.xm-ready .xm-sec { opacity: 0; transform: translateY(32px); }
  :root.xm-ready .xm-sec.xm-in {
    opacity: 1;
    transform: none;
    transition: opacity .75s cubic-bezier(.22, 1, .36, 1), transform .9s cubic-bezier(.22, 1, .36, 1);
  }
  :root.xm-ready .xm-sec .xm-kid { opacity: 0; transform: translateY(20px); }
  :root.xm-ready .xm-sec.xm-in .xm-kid {
    opacity: 1;
    transform: none;
    transition: opacity .6s cubic-bezier(.22, 1, .36, 1) calc(var(--xm-i, 0) * 70ms + 120ms),
                transform .7s cubic-bezier(.22, 1, .36, 1) calc(var(--xm-i, 0) * 70ms + 120ms);
  }
}

@keyframes xm-leave { to { opacity: 0; transform: translateY(-10px); filter: blur(3px); } }
@keyframes xm-enter { from { opacity: 0; transform: translateY(14px); } }
@keyframes xm-rise  { from { opacity: 0; transform: translateY(22px); } }

@media print {
  :root .xm-sec, :root .xm-kid { opacity: 1 !important; transform: none !important; }
}
