/* ---------- Fonts ---------- */
/* All self-hosted, SIL Open Font License (see assets/fonts/OFL-*.txt).
   Instrument Serif: Regular for "DESIGN" / "LOVE", Italic for "is celebrating what you".
   Instrument Sans Bold: the "I want to play!" thought cloud. */
@font-face {
  font-family: "Instrument Serif";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/instrument-serif-regular-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Instrument Serif";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/instrument-serif-regular-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Instrument Serif";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/instrument-serif-italic-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Instrument Serif";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/instrument-serif-italic-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Instrument Sans Regular: body text on the case study banner. */
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/instrument-sans-regular-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/instrument-sans-regular-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/instrument-sans-bold-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/instrument-sans-bold-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --font-display: "Instrument Serif", "Times New Roman", serif;
  --font-sans: "Instrument Sans", system-ui, sans-serif;
}

.font-display {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
}

.font-display-italic {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
}

/* ---------- Design tokens ---------- */
:root {
  /* Layout grid (Figma: 12 columns, stretch, auto width, 60px margin, 20px gutter on a 1440 canvas) */
  --canvas-width: 1440px;
  --canvas-min-height: 860px;
  --grid-columns: 12;
  --grid-margin: 60px;
  --grid-gutter: 20px;

  /* Figma variables */
  --color-lime-green: #b5ef5f;
  --size-s: 16px;

  /* Page backdrop: the space around and behind the 1440 canvas */
  --color-backdrop: #2a3ebe;
  --color-canvas: #FFFEF8;

  /* Typography (Figma collection "typography": size-xxl → --typography-size-xxl) */
  --typography-size-xxl: 128px;

  /* Space above the hero (the logo starts here). The "Click me" sticker and the paper grain on
     the logo follow it. */
  --hero-top: 40px;
}

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

html {
  overflow-x: clip;
}

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
  color: #1a1a1a;
  background: var(--color-backdrop);
}

img {
  max-width: 100%;
  display: block;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- Layout grid ---------- */
/* .container: the 1440px canvas, centred, with the grid's side margins.
   .grid: 12 stretch columns with 20px gutters; place children with grid-column (e.g. 1 / -1). */
.container {
  width: 100%;
  max-width: var(--canvas-width);
  margin-inline: auto;
  padding-inline: var(--grid-margin);
}

.grid {
  display: grid;
  grid-template-columns: repeat(var(--grid-columns), minmax(0, 1fr));
  column-gap: var(--grid-gutter);
}

/* Column overlay for checking alignment: press G (see main.js). */
.grid-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
}

.grid-overlay .grid {
  height: 100%;
}

.grid-overlay span {
  background: rgb(255 0 0 / 0.08);
}

/* ---------- Home frame ---------- */
/* Figma: Portfolio_02 > Portfolio_Idea2 (1440 × 1024). Everything that isn't on the grid is placed
   with the frame's own coordinates; horizontal positions use the same "% of frame width + px" that
   Figma reports, so they track the frame on narrower screens. The circle runs off the frame's
   right and bottom edges, as in Figma. Nothing shows outside the centred 1440 canvas: on wider
   screens the frame stays put and anything that runs off it (the hill) is cut at its edges.
   Height: the frame fills the browser window (100dvh) instead of a fixed 1024. The hero is
   pinned to the top; the hill, grass, cat and cloud keep their Figma distances from the bottom
   (written as 100% − (1024 − y)), so they always sit at the bottom of the window. Below
   --canvas-min-height (860) the frame stops shrinking (and scrolls) so the notepad nav and the
   cloud never run into the hero text. */
.home {
  position: relative;
  width: 100%;
  max-width: var(--canvas-width);
  height: 100vh;
  height: 100dvh;
  min-height: var(--canvas-min-height);
  margin-inline: auto;
  overflow: clip;
  /* So things inside can size from the frame's width (cqw), e.g. the notepad nav's 2 columns. */
  container-type: inline-size;
}

/* .canvas wraps .home: same centred 1440 box, but it doesn't clip, so it can draw the seams
   across the frame's edges while .home keeps cutting its own content at those edges.
   Seams: a dashed stroke down each side of the canvas, like a sewing seam / bullet-journal
   staples. Centre stroke (half outside, half inside the edge), 2px, round caps, 12px dashes with
   12px gaps (Figma-style: the round caps add 1px to each end, so each dash looks 14px long with
   10px between). As tall as the canvas, so they grow with it. The dash tile is an SVG mask; the
   colour comes from --seam-color. Drawn above the frame's content so the hill doesn't cover the
   inner half. */
:root {
  --seam-color: #000;
  --seam-weight: 2px;
}

/* Paper texture (Adobe Stock 2112880611) multiplied over the canvas colour. The image is greyscale,
   brightened so the paper's average tone is white: multiplied, the canvas keeps its colour and only
   the grain shows. The tile is the texture plus a flipped copy, so it repeats down long pages
   without a seam. It spans the canvas width. --paper-texture-fade (0–1) lays canvas colour back
   over it to soften the grain. */
:root {
  --paper-texture-fade: 0;
}

.canvas {
  position: relative;
  max-width: var(--canvas-width);
  margin-inline: auto;
  background-color: var(--color-canvas);
  background-image:
    linear-gradient(rgb(from var(--color-canvas) r g b / var(--paper-texture-fade)), rgb(from var(--color-canvas) r g b / var(--paper-texture-fade))),
    image-set(url("../images/paper-texture.jpg") 1x, url("../images/paper-texture@2x.jpg") 2x);
  background-size: 100% auto;
  background-repeat: repeat-y;
  background-blend-mode: normal, multiply;
}

.canvas::before,
.canvas::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 2;
  width: var(--seam-weight);
  background: var(--seam-color);
  pointer-events: none;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2' height='24'%3E%3Cline x1='1' y1='1' x2='1' y2='13' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") top / 2px 24px repeat-y;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2' height='24'%3E%3Cline x1='1' y1='1' x2='1' y2='13' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") top / 2px 24px repeat-y;
}

.canvas::before { left: calc(var(--seam-weight) / -2); }
.canvas::after  { right: calc(var(--seam-weight) / -2); }

/* Ellipse 1: the green hill (1199px circle, #849C61 with a #607246 stroke), top-left at
   (998, 691) on the 1440 frame; x is written as (66.67% + 38px) so it tracks the frame on
   narrower screens like the other elements. */
.home__circle {
  position: absolute;
  left: calc(66.6667% + 38px);
  top: calc(100% - 333px);
  width: 1199px;
  max-width: none;
  height: 1199px;
  pointer-events: none;
}

/* grass_scribbles: on the hill, top-left at (1125.3, 789.5) on the 1440 frame. */
.home__grass {
  position: absolute;
  left: calc(75% + 45.27px);
  top: calc(100% - 234.54px);
  width: 331.028px;
  max-width: none;
  height: 224.14px;
  pointer-events: none;
}

/* New nav (Figma "new nav" 2161:1198): the links written on a notepad page, scaled down to fill
   grid columns 1–2 exactly. Figma's drawing is 312 × 527.5 with Instrument Sans Bold 32px; the
   nav is that drawing scaled to the width of 2 columns + 1 gutter (203.33px on the 1440 frame,
   narrower on smaller screens, since the columns stretch). Everything inside is in em, so the
   font size sets the scale: font-size = 32px × (2-column width / 312). Its bottom stays 75.09px
   above the frame's bottom (as in Figma), so it stays put as the window height changes. Inside
   (at Figma's 32px scale): the four page links centred in a 146px column at x 85 with 24px gaps
   (first at y 96.61), "meet the cat" at (60, 406.61). The current page's link is blue. */
:root {
  --color-nav-current: #2a3ebe;
}

.notepad-nav {
  --nav-width: calc((100cqw - 2 * var(--grid-margin) - 11 * var(--grid-gutter)) / 6 + var(--grid-gutter));
  position: absolute;
  left: var(--grid-margin);
  top: calc(100% - 75.085px - 16.4852em);
  width: 9.75em;          /* 312 / 32: = --nav-width */
  height: 16.4852em;      /* 527.525 / 32 */
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: calc(var(--nav-width) * 32 / 312);
  line-height: normal;
}

/* The SVG is 2.5px (at 32px) bigger than the page on every side (its outline stroke). */
.notepad-nav__paper {
  position: absolute;
  left: -0.078125em;
  top: -0.078125em;
  width: 9.90622em;       /* 316.999 / 32 */
  max-width: none;
  height: 16.6414em;      /* 532.525 / 32 */
  pointer-events: none;
  /* A slight drop shadow (the same as the "Click me" sticker's), a little deeper while it's
     picked up and dragged. */
  filter: drop-shadow(0 4px 2px rgb(0 0 0 / 0.25));
  transition: filter 0.2s ease;
}

/* The notepad can be dragged anywhere on the page (main.js): it sits above the other artwork,
   and dragging doesn't select text or start the browser's own link/image drag. */
.notepad-nav {
  z-index: 3;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

.notepad-nav.is-dragging .notepad-nav__paper {
  filter: drop-shadow(0 12px 8px rgb(0 0 0 / 0.2));
}

.notepad-nav a {
  color: #000;
  text-decoration: none;
  white-space: nowrap;
}

.notepad-nav a[aria-current="page"] {
  color: var(--color-nav-current);
}

.notepad-nav__links a {
  position: relative;
  display: inline-block;
}

/* Hover/focus: a hand-drawn circle around the link, in the current-page blue (drawn by
   main.js — a new, slightly different loop each time, like circling it with a pen). */
.nav-circle {
  position: absolute;
  left: 0;
  top: 0;
  overflow: visible;
  pointer-events: none;
}

.nav-circle path {
  fill: none;
  stroke: var(--color-nav-current);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}

.nav-circle.is-drawn path {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 0.45s cubic-bezier(0.5, 0.05, 0.3, 1);
}

.nav-circle.is-erasing {
  opacity: 0;
  transition: opacity 0.2s ease;
}

@media (prefers-reduced-motion: reduce) {
  .nav-circle.is-drawn path {
    transition: none;
  }
}

.notepad-nav__links {
  position: absolute;
  left: 2.65625em;        /* 85 / 32 */
  width: 4.5625em;        /* 146 / 32 */
  top: 3.01906em;         /* 96.61 / 32 */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75em;            /* 24 / 32 */
  margin: 0;
  padding: 0;
  list-style: none;
}

.notepad-nav__cat {
  position: absolute;
  left: 1.875em;          /* 60 / 32 */
  top: 12.7066em;         /* 406.61 / 32 */
}

/* click_me_sticker (Figma 2168:1838): a 239.72px group, top right of the frame. The pink circle
   (39.86px into the group) starts on column 11 and its top lines up with the top of the hero
   block (--hero-top, where the logo starts): column 11 begins at 83.33% − 23.33px of the 1440 grid
   (60px margins, 20px gutters), so the group sits 39.86px up and left of that. The sticker: a
   160px pink (#ef5fa0) circle with an 8px black border and a soft drop shadow, the cat face
   (cat-sticker.svg) centred and tilted 8.13°. "Click me!" (Instrument Sans Bold 24px) runs along
   a 228px circle around it. The text is hidden until you hover the sticker, then writes itself on along the circle: it
   slides round into place while a sweep reveals it from the "C" to the "!". Only the sticker
   itself is the hover/click target. */
@property --sticker-reveal {
  syntax: "<angle>";
  inherits: false;
  initial-value: 165deg;
}

.cat-sticker {
  position: absolute;
  left: calc(83.3333% - 63.19px);
  top: calc(var(--hero-top) - 39.86px);
  width: 239.72px;
  height: 239.72px;
  pointer-events: none;
}

.cat-sticker__badge {
  position: absolute;
  left: 39.86px;
  top: 39.86px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 160px;
  height: 160px;
  border: 8px solid #000;
  border-radius: 93px;
  background: #ef5fa0;
  filter: drop-shadow(0 4px 2px rgb(0 0 0 / 0.25));
  pointer-events: auto;
}

/* In Figma the face sits in a 95.2 × 99.9 box (the SVG overhangs it by 2px at the sides and
   bottom), rotated about that box's centre: the same as rotating the SVG and moving it 1px down
   the tilted axis. */
.cat-sticker__cat {
  width: 99.2156px;
  max-width: none;
  height: 101.917px;
  rotate: 8.13deg;
  translate: -0.14px 0.99px;
}

.cat-sticker__label {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 24px;
  fill: #000;
  /* Hidden: rotated back a little and swept away. Conic angles are clockwise from 12 o'clock;
     the text spans about 105°–160°. */
  rotate: 20deg;
  --sticker-reveal: 165deg;
  -webkit-mask: conic-gradient(transparent 0 var(--sticker-reveal), #000 var(--sticker-reveal) 168deg, transparent 168deg);
  mask: conic-gradient(transparent 0 var(--sticker-reveal), #000 var(--sticker-reveal) 168deg, transparent 168deg);
  transition: rotate 0.3s ease-in, --sticker-reveal 0.3s ease-in;
}

.cat-sticker:hover .cat-sticker__label,
.cat-sticker:focus-visible .cat-sticker__label {
  rotate: 0deg;
  --sticker-reveal: 98deg;
  transition: rotate 0.55s cubic-bezier(0.2, 0.8, 0.3, 1), --sticker-reveal 0.55s cubic-bezier(0.3, 0.6, 0.3, 1);
}

.cat-sticker:focus-visible {
  outline: none;
}

.cat-sticker:focus-visible .cat-sticker__badge {
  outline: 3px solid var(--color-nav-current);
  outline-offset: 4px;
}

@media (prefers-reduced-motion: reduce) {
  .cat-sticker__label,
  .cat-sticker:hover .cat-sticker__label,
  .cat-sticker:focus-visible .cat-sticker__label {
    transition: none;
  }
}

/* Static nav (Figma "nav bar" + "meet the cat"): the previous nav, hidden for now (the [hidden]
   attribute in index.html). Instrument Sans Bold 18px, 49px up from the bottom of the frame
   (y 975). The page links sit in a row from column 1 with 64px gaps; "meet the cat" starts on
   column 8. */
.static-nav[hidden] {
  display: none;
}

.static-nav {
  position: sticky;
  inset-inline: 0;
  top: calc(100% - 49px);
  z-index: 1;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 18px;
  line-height: normal;
}

.static-nav a {
  color: #000;
  text-decoration: none;
  white-space: nowrap;
}

.static-nav__links {
  grid-column: 1 / 8;
  display: flex;
  gap: 64px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.static-nav__cat {
  grid-column: 8;
}

/* cat_vector: the 2D cat (frame 2105:473) and its shadow, at x (83.33% − 43px), y 640.37. */
.home__cat {
  position: absolute;
  left: calc(83.3333% - 43px);
  top: calc(100% - 383.63px);
}

/* On the homepage the shadow is dark green (#607246, as in Figma): the shared cat-shadow.svg
   shape, filled with that colour here. The file itself stays grey for other uses. */
.home__cat-shadow {
  position: absolute;
  left: 110.61px;
  top: 303.63px;
  width: 122.075px;
  height: 22.928px;
  transform: translateX(-50%);
  background: #607246;
  -webkit-mask: url("../images/cat-shadow.svg") center / 100% 100% no-repeat;
  mask: url("../images/cat-shadow.svg") center / 100% 100% no-repeat;
}

/* The cat's hop, from the Figma motion: three 14.872px hops in the first third of a 2 s loop. */
.home__cat-art {
  position: relative;
  left: -1.85px;
  width: 226.93px;
  max-width: none;
  height: 316.651px;
  animation: cat-hop 2s linear infinite;
}

/* Dragging the cat (assets/js/home-cat.js): while it's held or falling, the plain artwork hides and
   the animated rig (same drawing, same box) takes its place, above the thought cloud. */
.home__cat {
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

.home__cat.is-held {
  z-index: 1;
}

.home__cat-rig {
  position: absolute;
  left: -1.85px;
  top: 0;
  width: 226.93px;
  height: 316.651px;
  overflow: visible;
  visibility: hidden;
  pointer-events: none;
}

.home__cat.is-held .home__cat-rig {
  visibility: visible;
}

.home__cat.is-held .home__cat-art {
  visibility: hidden;
}

@keyframes cat-hop {
  0%      { translate: 0 0; }
  4.863%  { translate: 0 -14.872px; }
  10.293% { translate: 0 0; }
  17.15%  { translate: 0 -14.872px; }
  22.678% { translate: 0 0; }
  28.759% { translate: 0 -14.872px; }
  33.956% { translate: 0 0; }
  100%    { translate: 0 0; }
}

/* iwanttoplay: mirrored thinking cloud with "I want" / "to" (32px) and "play!" (48px) in
   Instrument Sans Bold, each word rotated. Group at x (66.67% − 7px), y 498.63; each word is
   centred in the box Figma gives for it. */
.home__play {
  position: absolute;
  left: calc(66.6667% - 7px);
  top: calc(100% - 525.37px);
  width: 224px;
  height: 235.567px;
  margin: 0;
}

.home__cloud {
  position: absolute;
  inset: 0;
  width: 224px;
  max-width: none;
  height: 235.567px;
  transform: scaleX(-1);
}

.home__play-word {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-sans);
  font-weight: 700;
  line-height: normal;
  color: #000;
  white-space: nowrap;
}

.home__play-word > span {
  display: block;
  /* Figma trims the text box to cap height + baseline; centre the words the same way. */
  text-box: trim-both cap alphabetic;
  rotate: var(--rotate);
}

.home__play-word--i-want { left: 30px;  top: 53.37px; width: 92.318px;  height: 28.949px; font-size: 32px; --rotate: -3.78deg; }
.home__play-word--to     { left: 130px; top: 52.37px; width: 37.03px;   height: 29.304px; font-size: 32px; --rotate: 11.89deg; }
.home__play-word--play   { left: 64px;  top: 82.37px; width: 113.167px; height: 51.819px; font-size: 48px; --rotate: 9.11deg; }

.boil-filters {
  position: absolute;
  width: 0;
  height: 0;
}

/* Hand-drawn "boil" (posterized time) on the thought cloud, every piece on its own: the bubble,
   its three trailing circles, and the words "I want", "to" and "play!". Each piece steps between
   four soft wobble filters (#boil-1–4 in index.html) on held frames at about 4 fps, and nudges a
   fraction of a pixel on the same beat, at a slightly different pace so they never line up.
   The cloud's shapes come from thinking-cloud.svg, put inline by main.js so each can move; the
   text wobbles on the inner span (before its rotation), the nudges on the outer box. */
.home__cloud-part {
  transform-box: fill-box;
  transform-origin: center;
  animation: play-boil var(--boil-loop) steps(1, end) infinite,
    play-jitter var(--boil-loop) steps(1, end) infinite;
}

.home__cloud-bubble   { --boil-loop: 1s; }
.home__cloud-circle-1 { --boil-loop: 0.96s; animation-delay: -0.2s; }
.home__cloud-circle-2 { --boil-loop: 1.08s; animation-delay: -0.45s; }
.home__cloud-circle-3 { --boil-loop: 0.88s; animation-delay: -0.7s; }

.home__play-word {
  animation: play-jitter var(--boil-loop) steps(1, end) infinite;
}

.home__play-word > span {
  animation: play-boil var(--boil-loop) steps(1, end) infinite;
}

.home__play-word--i-want { --boil-loop: 1.12s; }
.home__play-word--to     { --boil-loop: 0.92s; }
.home__play-word--play   { --boil-loop: 1.04s; }

.home__play-word--i-want,
.home__play-word--i-want > span { animation-delay: -0.3s; }
.home__play-word--to,
.home__play-word--to > span     { animation-delay: -0.55s; }
.home__play-word--play,
.home__play-word--play > span   { animation-delay: -0.8s; }

@keyframes play-boil {
  0%   { filter: url(#boil-1); }
  25%  { filter: url(#boil-2); }
  50%  { filter: url(#boil-3); }
  75%  { filter: url(#boil-4); }
  100% { filter: url(#boil-1); }
}

@keyframes play-jitter {
  0%   { translate: 0 0;             rotate: 0deg; }
  25%  { translate: 0.4px -0.3px;    rotate: 0.22deg; }
  50%  { translate: -0.3px 0.4px;    rotate: -0.15deg; }
  75%  { translate: 0.25px 0.3px;    rotate: 0.12deg; }
  100% { translate: 0 0;             rotate: 0deg; }
}

@media (prefers-reduced-motion: reduce) {
  .home__cat-art,
  .home__play-word > span,
  .home__cloud-part,
  .home__play-word {
    animation: none;
  }
}

/* ---------- Hero ---------- */
/* hero_text_animated: Instrument Serif, starting at column 1 and ending on the right edge of
   column 9. On the 1440 canvas that is exactly --typography-size-xxl (128px); on narrower
   screens (e.g. 1280 laptops) the text scales down with the columns so it still ends on column 9.
   Line spacing (0.743em, from Figma), letter-spacing and the warp canvas are relative to the font
   size, so they follow it. */
.hero {
  /* Longest line ("DESIGN is celebrating", to the tip of the "g", with the letter-spacing) in em. */
  --hero-line-em: 7.6953;
  --hero-columns: 9;
  /* The hero's type size, shared by the wordmark and the hero text (cqi is measured on the
     element that uses it, i.e. against this section's width). */
  --hero-size: min(
    var(--typography-size-xxl),
    calc(
      (var(--hero-columns) * (100cqi - (var(--grid-columns) - 1) * var(--grid-gutter)) / var(--grid-columns)
        + (var(--hero-columns) - 1) * var(--grid-gutter))
      / var(--hero-line-em)
    )
  );
  position: relative;
  padding-top: var(--hero-top);
  /* Lets the hero text size itself from the grid's real width (cqi), not the window's. */
  container-type: inline-size;
}

/* myName (Figma 2208:542): the "lilydeedesign" wordmark above the hero text, used like a logo:
   "lily" and "dee" Bold, "design" Regular, set solid. It's the Figma export's outlines
   (assets/images/wordmark.svg) inline, with the viewBox cropped to the ink, so the letters span
   exactly columns 1–2 of the grid at every width (about 203 × 32 on the 1440 canvas). Its
   baseline sits 48px above the hero text (the descenders hang into that space), and its top is
   at y 48, the same as the space above.
   On load each word draws on like After Effects' trim paths: a thin black outline traces every
   letter (one after another, as each word is one path; the three words start a beat apart), then
   the ink fills in and the outline fades. */
.wordmark {
  --wordmark-columns: 2;
  /* The logo's width (its ink), and its descender: the part below the baseline, 0.0352 of the
     width (14.95 of 424.23 in the SVG). */
  --wordmark-width: calc(
    var(--wordmark-columns) * (100cqi - (var(--grid-columns) - 1) * var(--grid-gutter)) / var(--grid-columns)
      + (var(--wordmark-columns) - 1) * var(--grid-gutter)
  );
  grid-column: 1 / span var(--hero-columns);
  justify-self: start;
  position: relative;
  width: var(--wordmark-width);
  margin: 0 0 calc(48px - var(--wordmark-width) * 0.0352);
  line-height: 0;
}

.wordmark__logo {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

/* The paper texture over the ink: the canvas's own texture, inverted and brightened, screened
   over the letters, so the paper's fibres show as faint light grain in the black (over the cream
   paper it adds next to nothing). Sized and positioned like the canvas background (canvas width =
   this section's width + its 60px margins; the logo sits 60px in and --hero-top down), so the grain
   lines up with the paper around it. --wordmark-grain sets how strong it is. */
.wordmark::after {
  --wordmark-grain: 4;
  content: "";
  position: absolute;
  inset: 0;
  background: image-set(url("../images/paper-texture.jpg") 1x, url("../images/paper-texture@2x.jpg") 2x)
    calc(-1 * var(--grid-margin)) calc(-1 * var(--hero-top)) / calc(100cqi + 2 * var(--grid-margin)) auto repeat-y;
  filter: invert(1) brightness(var(--wordmark-grain));
  mix-blend-mode: screen;
  pointer-events: none;
}

/* Trim-paths draw-on: each word's outline is one dash as long as the path (pathLength 1), pushed
   off by its full length and then pulled back to 0; the fill comes in as it finishes. The stroke
   is ~1px on screen (2 units at about half size). */
.wordmark__word {
  fill: transparent;
  stroke: #000;
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-dasharray: 1 1;
  stroke-dashoffset: 1;
  animation:
    wordmark-draw 1.6s cubic-bezier(0.45, 0, 0.25, 1) forwards,
    wordmark-fill 0.5s ease-out 1.35s forwards;
}

.wordmark__word--dee {
  animation-delay: 0.25s, 1.6s;
}

.wordmark__word--design {
  animation-delay: 0.5s, 1.85s;
}

@keyframes wordmark-draw {
  to { stroke-dashoffset: 0; }
}

@keyframes wordmark-fill {
  to {
    fill: #000;
    stroke-opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .wordmark__word {
    fill: #000;
    stroke: none;
    animation: none;
  }
}

.hero-text {
  grid-column: 1 / span var(--hero-columns);
  position: relative;
  width: fit-content;
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--hero-size);
  line-height: 0.743;
  /* A hair of spacing (0.12px at 128px) so the "g" of "celebrating" lands exactly on the right
     edge of column 9. */
  letter-spacing: 0.000957em;
  color: #000;
}

.hero-text__line {
  display: block;
  white-space: nowrap;
}

/* While the warp canvas draws the text, the real text stays in place (selectable, readable by
   screen readers) but invisible. */
.hero-text.is-warping .hero-text__line {
  color: transparent;
}

/* The warp canvas overhangs the text so letters can stretch past their box. */
.hero-text__warp {
  visibility: hidden;
  position: absolute;
  left: -4%;
  top: -20%;
  width: 108%;
  height: 140%;
  pointer-events: none;
}

.hero-text.is-warping .hero-text__warp {
  visibility: visible;
}
