@font-face {
  font-family: "Cormorant Garamond";
  src: url("fonts/cormorant-garamond.woff2") format("woff2");
  font-weight: 300 700;
  font-display: swap;
}

@font-face {
  font-family: "Josefin Sans";
  src: url("fonts/josefin-sans.woff2") format("woff2");
  font-weight: 100 700;
  font-display: swap;
}

:root {
  --flax: #d8ccb3;
  --flax-light: #e8dfcb;
  --flax-shade: #b9aa8c;
  --sage: #8a9a7b;
  --sage-deep: #4f5b45;
  --woad: #4d6275;
  --woad-deep: #3d4f60;
  --thread: #ede3cc;
  --dawn: #f2b880;
  --graphite: #3b342a;
  /* The whole page fits the screen, the name above the hoop included: it never scrolls. */
  --hoop: min(72vmin, 640px, calc(100svh - 230px));
  /* main.js swaps this flat cross-weave for a generated linen tile. */
  --weave:
    repeating-linear-gradient(0deg, rgb(255 250 238 / .18) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(90deg, rgb(120 100 70 / .12) 0 1px, transparent 1px 3px);
  color-scheme: light;
}

* { box-sizing: border-box; }

/* No scrolling, so a finger dragged over the linen plays with the cloth (linen.js); pinching still zooms. */
html, body { margin: 0; height: 100%; overflow: hidden; overscroll-behavior: none; }

body {
  height: 100svh;
  touch-action: pinch-zoom;
  background-color: var(--flax);
  background-image: var(--weave);
  background-size: 350px;
  color: var(--graphite);
  font-family: "Josefin Sans", "Avenir Next", "Segoe UI", sans-serif;
}

/* The linen as a cloth with its own mesh (linen.js), or its folds painted where it cannot have one (fold.js),
   behind everything on the page and under the morning light. The mesh comes in flat, as the page's linen is
   drawn, and only then falls into its folds: it shows at once, there is nothing to fade between. */
canvas.linen,
canvas.linen-folds {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  pointer-events: none;
}
canvas.linen-folds { mix-blend-mode: multiply; }
canvas.linen { opacity: 0; }
canvas.linen.ready { opacity: 1; }

/* Morning light from the upper right, and the cloth falling into shade at the edges. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(120% 90% at 82% 8%, rgb(255 226 178 / .5), transparent 60%),
    radial-gradient(140% 120% at 50% 50%, transparent 55%, rgb(92 74 48 / .28));
}

.page {
  position: relative;
  height: 100svh;
  display: grid;
  place-items: center;
  /* Room above the hoop for the site's name. */
  padding: max(56px, 16vmin) 16px 96px;
}

.stage { position: relative; width: var(--hoop); }

/* The embroidery hoop: taut cloth inside, a beech ring and its brass screw on top. */
.hoop {
  position: relative;
  width: var(--hoop);
  aspect-ratio: 1;
  margin: 0;
  filter: drop-shadow(0 18px 22px rgb(70 52 30 / .22)) drop-shadow(0 2px 3px rgb(70 52 30 / .25));
}

.cloth {
  position: absolute;
  inset: 2.2%;
  border-radius: 50%;
  overflow: hidden;
  background-color: var(--flax-light);
  background-image:
    radial-gradient(circle at 50% 42%, rgb(255 251 240 / .55), transparent 70%),
    var(--weave);
  background-size: auto, 350px;
  box-shadow: inset 0 0 0 1px rgb(90 70 40 / .2), inset 0 6px 18px rgb(80 60 35 / .25);
}

.cloth canvas,
.cloth .drawing {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

.cloth canvas {
  opacity: 0;
  transition: opacity 1.6s ease;
}

.hoop .cloth canvas.ready { opacity: 1; }
.hoop[data-scene="3d"] canvas.thread,
.hoop[data-scene="dibujo"] canvas.felt { display: none; }
/* Both scenes are clicked, tapped or swiped through the day (main.js), so the page must not scroll under them. */
.hoop:not(.fallback) .cloth { cursor: pointer; touch-action: none; }

.ring {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

/* The drawing: embroidered in coloured thread over washes of dye, shown only if the embroidered day cannot
   start. main.js then turns each line (.ink) into running stitches; until it has, nothing shows, so the
   hoop opens empty and is sewn from nothing (noscript.css shows the plain lines without JavaScript). */
.drawing:not(.stitched) .lines,
.drawing:not(.stitched) .washes { opacity: 0; }

.ink {
  fill: none;
  stroke: var(--thread-colour, var(--graphite));
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.ink.faint { stroke-width: 2.2; opacity: .75; }
.ink.sewn { display: none; }

.stitch {
  stroke: var(--thread-colour, var(--graphite));
  stroke-width: 4.4;
  stroke-linecap: round;
}

.stitches.faint { opacity: .8; }
.stitches.faint .stitch { stroke-width: 3.2; }

/* The light along each thread's twist. */
.sheen {
  stroke: rgb(255 248 230 / .38);
  stroke-width: 1.3;
  stroke-linecap: round;
}

.t-sun { --thread-colour: #d9822b; }
.t-ray { --thread-colour: #e4a23f; }
.t-hill { --thread-colour: #56634a; }
.t-grass { --thread-colour: #7d8b55; }
.t-bark { --thread-colour: #6b472d; }
.t-leaf { --thread-colour: #4f6136; }
.t-leaf-light { --thread-colour: #7f9150; }
.t-woad { --thread-colour: #34507a; }
.t-hair { --thread-colour: #4b3122; }
.t-wool { --thread-colour: #9a7040; }

.wash { opacity: .5; mix-blend-mode: multiply; }
.wash-glow { opacity: .9; mix-blend-mode: normal; }
.wash-sun { opacity: .8; }
.wash-leaves { opacity: .42; }
.wash-trunk { opacity: .28; }
.wash-hills { opacity: .32; }
.wash-fabric { opacity: .55; }
.wash-branch { opacity: .34; }
.wash-wool { opacity: .5; }
.wash-hair { opacity: .6; }

.swing { transform-origin: 550px 314px; }
.rays { transform-origin: 730px 650px; }

/* main.js adds .drawing-in once each stitch has its moment (--d): the lines are sewn one stitch at a time. */
.drawing-in .stitch,
.drawing-in .sheen {
  opacity: 0;
  animation: sew .14s ease-out forwards;
  animation-delay: var(--d, 0s);
}

.drawing-in .washes {
  opacity: 0;
  animation: soak 2.4s ease 4.6s forwards;
}

.drawing-in .sunrise { animation: rise 9s cubic-bezier(.25, .6, .3, 1) 4.4s both; }
.drawing-in .swing { animation: sway 3.6s ease-in-out 6.4s infinite alternate both; }
.drawing-in .rays { animation: turn 60s linear 6s infinite; }

@keyframes sew { from { opacity: 0; stroke-width: 0; } to { opacity: 1; } }
@keyframes soak { to { opacity: 1; } }
@keyframes rise { from { transform: translateY(70px); } to { transform: translateY(-34px); } }
@keyframes sway { from { transform: rotate(-3.2deg); } to { transform: rotate(3.2deg); } }
@keyframes turn { to { transform: rotate(360deg); } }

/* The site's name, embroidered in satin stitch on the linen above the hoop (main.js); plain type in the
   thread's blue until it is, and without JavaScript. */
.site-name {
  position: absolute;
  bottom: 100%;
  left: 50%;
  translate: -50% 0;
  margin: 0 0 clamp(18px, 4vmin, 40px);
  /* The type is there for screen readers and to size the name; it shows, in the thread's blue, only without
     JavaScript (noscript.css) or if the embroidery fails (.plain). */
  color: transparent;
  font: 700 clamp(30px, 6.4vmin, 58px)/1 "Cormorant Garamond", "Iowan Old Style", Georgia, serif;
  letter-spacing: .03em;
  white-space: nowrap;
}

.site-name.plain { color: var(--woad-deep); }

.site-name canvas { display: block; animation: sewn-in .6s ease both; }

@keyframes sewn-in { from { opacity: 0; } }

.site-name.embroidered .site-name-text {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

/* Once the linen is cloth, the name and the label are sewn into it and move with its folds (linen.js): the
   page's copies, the same pictures in the same places while the cloth is still flat, step aside. */
.linen-cloth .site-name canvas,
.linen-cloth .label canvas { visibility: hidden; }

/* The label: a woven tag sewn onto the linen under the hoop, its words embroidered (main.js), lying on the
   cloth with the name (linen.js). The type sizes it and stays for screen readers; it shows, in the thread's
   blue, only without JavaScript (noscript.css) or if the embroidery fails (.plain). */
.label {
  position: absolute;
  top: 100%;
  left: 50%;
  translate: -50% 0;
  margin: clamp(12px, 2.4vmin, 24px) 0 0;
  padding: 12px 28px 10px;
  display: grid;
  gap: 3px;
  color: transparent;
  font-weight: inherit;
  white-space: nowrap;
}

.label.plain { color: var(--woad-deep); }

.label canvas { position: absolute; pointer-events: none; animation: sewn-in .6s ease both; }

.label-title {
  font-family: "Cormorant Garamond", "Iowan Old Style", Georgia, serif;
  font-weight: 600;
  font-size: clamp(1.5rem, 3.6vmin, 2.6rem);
  line-height: 1;
  letter-spacing: .01em;
}

.label-line {
  font-weight: 400;
  font-size: clamp(.9rem, 1.8vmin, 1.1rem);
  letter-spacing: .14em;
  padding-left: .15em;
}

.switch {
  position: fixed;
  right: 16px;
  bottom: 16px;
  padding: 10px 14px;
  border: 0;
  background: rgb(232 223 203 / .7);
  color: var(--graphite);
  font: 400 .95rem/1 "Josefin Sans", sans-serif;
  letter-spacing: .04em;
  text-decoration: underline dashed rgb(59 52 42 / .5);
  text-underline-offset: 5px;
  border-radius: 3px;
  cursor: pointer;
}

.switch:hover { background: rgb(232 223 203 / .95); }

.switch:focus-visible,
.label:focus-visible {
  outline: 2px solid var(--woad);
  outline-offset: 3px;
}

@media (max-width: 640px), (max-aspect-ratio: 3/4) {
  :root { --hoop: min(90vw, 58svh); }

  .page { padding-top: 32px; }

  .stage { display: grid; justify-items: center; }

  .site-name {
    position: relative;
    bottom: auto;
    left: auto;
    translate: none;
    margin: 0 0 clamp(24px, 6vw, 36px);
    font-size: clamp(38px, 11vw, 54px);
  }

  .label {
    position: relative;
    top: auto;
    left: auto;
    translate: none;
    margin-top: clamp(14px, 4vw, 24px);
  }

  .switch { left: 50%; right: auto; translate: -50% 0; }
}

/* With reduced motion main.js never adds .drawing-in: the drawing stands finished. */
@media (prefers-reduced-motion: reduce) {
  .cloth canvas { transition: none; }
  .site-name canvas,
  .label canvas { animation: none; }
}
