/* =========================================================
   Cianotipia
   ---------------------------------------------------------
   Anna Atkins, 1843: lay the specimen on sensitised paper,
   leave it in the sun, wash it. Everything the specimen
   covered stays pale, everything else turns Prussian blue.

   That is the whole system here. Blue is not an accent, it
   is the paper. The shapes are the absence of it.
   ========================================================= */

:root{
  /* the print */
  --ink:      oklch(0.185 0.052 249);   /* deepest exposure             */
  --prussian: oklch(0.265 0.068 246);   /* the classic cyanotype blue   */
  --marine:   oklch(0.375 0.082 243);
  --wash:     oklch(0.615 0.072 236);
  --pale:     oklch(0.815 0.045 232);
  --frost:    oklch(0.930 0.022 228);   /* unexposed paper, the "white" */

  /* the only two things on the page that are not blue */
  --paper:    oklch(0.947 0.014 88);    /* warm stock, for the letter   */
  --iron:     oklch(0.685 0.108 62);    /* ferric ochre, used sparingly */

  --rail-w: 200px;
  --pad: clamp(1.25rem, 5vw, 4rem);
  --sec-y: clamp(5.5rem, 14vw, 11rem);

  --display: "Bodoni Moda", Didot, "Times New Roman", serif;
  --sans: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --hand: "Playwrite ES", "Snell Roundhand", cursive;

  /* ease-out-expo. nothing on this page bounces. */
  --expo: cubic-bezier(0.16, 1, 0.30, 1);
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}

body{
  margin:0;
  background:var(--ink);
  color:var(--frost);
  font-family:var(--sans);
  font-size:clamp(1rem,0.96rem + 0.2vw,1.06rem);
  line-height:1.65;
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
}
body.is-locked{overflow:hidden}

img{max-width:100%;height:auto;display:block}
button{font:inherit;color:inherit}
a{color:inherit}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.defs{position:absolute;width:0;height:0;overflow:hidden}

/* z-index 1 keeps every drawing behind the words. they are
   wallpaper, not content. */
.wrap{position:relative;z-index:1;width:100%;max-width:1200px;margin-inline:auto;padding-inline:var(--pad)}
main{position:relative;z-index:1}

/* =========================================================
   PAPER GRAIN
   A cyanotype is a physical print on cotton rag. Without
   tooth, the blue just reads as a CSS background colour.
   ========================================================= */
.grain{
  position:fixed;inset:0;z-index:70;pointer-events:none;
  opacity:.20;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* =========================================================
   THE SHAPES
   Drawn by tools/draw-shapes.mjs. Used as masks so one file
   can be any colour at any size.
   ========================================================= */
.bot{
  position:absolute;display:block;pointer-events:none;z-index:0;
  background-color:currentColor;
  mask-repeat:no-repeat;mask-size:contain;mask-position:center;
  -webkit-mask-repeat:no-repeat;-webkit-mask-size:contain;-webkit-mask-position:center;
  transform-origin:50% 100%;
  will-change:translate;
}
.bot--arch   {mask-image:url(../media/shapes/arch.svg);   -webkit-mask-image:url(../media/shapes/arch.svg);   aspect-ratio:400/520}
.bot--grain  {mask-image:url(../media/shapes/grain.svg);  -webkit-mask-image:url(../media/shapes/grain.svg);  aspect-ratio:460/300}
.bot--pebbles{mask-image:url(../media/shapes/pebbles.svg);-webkit-mask-image:url(../media/shapes/pebbles.svg);aspect-ratio:1}
.bot--dome   {mask-image:url(../media/shapes/dome.svg);   -webkit-mask-image:url(../media/shapes/dome.svg);   aspect-ratio:380/260}
.bot--rings  {mask-image:url(../media/shapes/rings.svg);  -webkit-mask-image:url(../media/shapes/rings.svg);  aspect-ratio:1}
.bot--stipple{mask-image:url(../media/shapes/stipple.svg);-webkit-mask-image:url(../media/shapes/stipple.svg);aspect-ratio:1}

/* nothing drifts in sync, or the page reads as a carousel.
   sway uses `rotate` and the scroll drift uses `translate`,
   which are separate properties, so they compose cleanly. */
@keyframes sway  {50%{rotate: 1.2deg}}
@keyframes sway-b{50%{rotate:-1.5deg}}
.hero__arch    {animation:sway   19s ease-in-out infinite}
.hero__grain   {animation:sway-b 13s ease-in-out infinite}
.about__stip   {animation:sway   23s ease-in-out infinite}
.voices__dome  {animation:sway-b 17s ease-in-out infinite}
.letter__peb   {animation:sway   21s ease-in-out infinite}
.plate__rings  {animation:sway-b 15s ease-in-out infinite}

/* =========================================================
   NAVIGATION
   ========================================================= */
.rail{
  position:fixed;left:var(--pad);top:50%;translate:0 -50%;
  z-index:60;display:none;flex-direction:column;gap:.75rem;
}
.rail a{
  position:relative;text-decoration:none;color:var(--frost);opacity:.58;
  font-size:.66rem;font-weight:600;letter-spacing:.2em;text-transform:uppercase;
  transition:opacity .4s var(--expo),translate .4s var(--expo);
}
.rail a::before{
  content:"";position:absolute;left:-1.15rem;top:50%;width:.75rem;height:1px;
  background:currentColor;scale:0 1;transform-origin:right center;
  transition:scale .4s var(--expo);
}
.rail a:hover,.rail a.is-active{opacity:1;translate:4px 0}
.rail a.is-active::before{scale:1 1;transform-origin:left center}
@media (min-width:1100px){.rail{display:flex}}

.menu-btn{
  position:fixed;top:1rem;right:1rem;z-index:90;
  width:46px;height:46px;border-radius:50%;cursor:pointer;
  background:color-mix(in oklch,var(--ink) 88%,transparent);
  color:var(--frost);
  border:1px solid color-mix(in oklch,var(--frost) 30%,transparent);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  display:grid;place-items:center;
}
.menu-btn__bars{display:block;width:17px}
.menu-btn__bars i{display:block;height:1.5px;background:currentColor;transition:translate .3s var(--expo),rotate .3s var(--expo)}
.menu-btn__bars i+i{margin-top:5px}
.menu-btn[aria-expanded="true"] i:first-child{translate:0 3.25px;rotate:45deg}
.menu-btn[aria-expanded="true"] i:last-child{translate:0 -3.25px;rotate:-45deg}
@media (min-width:1100px){.menu-btn{display:none}}

.drawer{
  position:fixed;inset:0;z-index:85;background:var(--ink);
  display:flex;flex-direction:column;justify-content:center;gap:.35rem;
  padding:var(--pad);overflow:hidden;
}
.drawer[hidden]{display:none}
.drawer__bot{color:var(--marine);opacity:.45;right:-14%;bottom:-8%;width:min(58vw,300px)}
.drawer a{
  position:relative;z-index:1;text-decoration:none;
  font-family:var(--display);font-weight:700;
  font-size:clamp(2.1rem,11vw,3.4rem);line-height:1.2;
}
.drawer a:active{color:var(--wash)}

/* =========================================================
   TYPE
   ========================================================= */
.eyebrow{
  font-size:.66rem;font-weight:600;letter-spacing:.24em;text-transform:uppercase;
  margin:0 0 1.6rem;opacity:.55;
}
.display{
  font-family:var(--display);font-weight:700;font-optical-sizing:auto;
  font-size:clamp(2rem,5.6vw,3.7rem);line-height:1.06;letter-spacing:-.015em;
  margin:0 0 1.3rem;text-wrap:balance;
}
.lede{max-width:56ch;margin:0;opacity:.72;font-size:clamp(1rem,2.1vw,1.14rem)}
.sec-head{margin-bottom:clamp(3rem,8vw,5.5rem);max-width:46ch}

/* now sits above the number, so the margin flips to the bottom */
.script{
  font-family:var(--hand);font-weight:300;
  font-size:clamp(1.15rem,4.2vw,2.1rem);line-height:1.1;
  color:var(--iron);margin:0 0 .35rem;
  rotate:-3deg;transform-origin:left center;
}

/* =========================================================
   PHOTO PLATES
   She stays in full colour. The photos are the one warm human
   thing on the page and tinting them was fighting that.

   The arch is a fixed frame and the photo moves inside it:
   a slow push in on hover, so the picture leans toward you
   rather than changing colour.
   ========================================================= */
/* the padding reserves the room the plate number sits in, so it
   never collides with whatever block follows on a narrow screen */
.plate{margin:0;position:relative;width:100%;padding-bottom:2.4rem}
.plate__arch{
  position:relative;overflow:hidden;
  border-radius:999px 999px 8px 8px;
  background:var(--marine);
  box-shadow:0 30px 70px color-mix(in oklch,var(--ink) 70%,transparent);
  transition:box-shadow .8s var(--expo),translate .8s var(--expo);
}
.plate__img{
  width:100%;aspect-ratio:3/4;object-fit:cover;
  transition:scale 1.1s var(--expo);
  will-change:scale;
}
.plate__arch:hover,.plate__arch:focus-within{
  translate:0 -8px;
  box-shadow:0 42px 90px color-mix(in oklch,var(--ink) 78%,transparent);
}
.plate__arch:hover .plate__img,
.plate__arch:focus-within .plate__img{scale:1.06}

.plate__cap{
  position:absolute;left:.2rem;bottom:.5rem;
  font-family:var(--display);font-style:italic;font-size:.95rem;
  letter-spacing:.08em;opacity:.62;
}

/* =========================================================
   PORTADA
   ========================================================= */
.hero{
  position:relative;min-height:100svh;overflow:hidden;
  display:flex;flex-direction:column;justify-content:center;
  padding:clamp(5.5rem,13vw,7rem) 0 4.5rem;
  background:
    radial-gradient(115% 80% at 78% 8%, var(--prussian), transparent 62%),
    var(--ink);
}
@media (min-width:1100px){.hero{padding-left:var(--rail-w)}}

.hero__arch {color:var(--marine);opacity:.6;left:-11%;top:-4%;width:min(46vw,360px)}
.hero__grain{color:var(--wash); opacity:.3;right:-8%;bottom:2%;width:min(62vw,440px)}

.hero__grid{position:relative;z-index:1;display:grid;gap:clamp(2.5rem,6vw,4.5rem);align-items:center}
.hero__type{will-change:translate,opacity}
.hero__grid>*{min-width:0}
@media (min-width:920px){.hero__grid{grid-template-columns:1.18fr .82fr}}

/* Two digits instead of a ten-letter word, so it can go much bigger.
   Bodoni's figures have far more contrast than its caps at this size,
   which is the whole reason for setting the number rather than
   spelling it out. */
.giant{
  font-family:var(--display);font-weight:900;font-optical-sizing:auto;
  margin:0;line-height:.8;letter-spacing:-.045em;
  font-size:clamp(7rem,30vw,15rem);
}
.giant__line{display:block}
/* every digit is its own span, so the number can expose across */
.giant .ltr{display:inline-block;will-change:opacity,translate,filter}
body.is-loading .giant .ltr{opacity:0}
.giant .ltr.is-lit{animation:expose 1.1s var(--expo) both}
@keyframes expose{
  from{opacity:0;translate:0 .3em;filter:blur(16px)}
  to  {opacity:1;translate:0 0;   filter:blur(0)}
}

/* =========================================================
   HERO ENTRANCE
   Everything arrives in reading order rather than at once:
   the label, then the handwriting wiping in left to right the
   way it would actually be written, then the digits, then the
   rest. app.js adds .is-ready once the display face has loaded,
   so nothing animates in a fallback serif and then reflows.
   ========================================================= */
body.is-loading .hero__type > *:not(.giant),
body.is-loading .hero__plate,
body.is-loading .cue{opacity:0}

.hero.is-ready .eyebrow    {animation:rise .85s var(--expo) .05s both}
.hero.is-ready .script     {animation:write 1.1s var(--expo) .28s both}
.hero.is-ready .hero__name {animation:rise .85s var(--expo) 1.05s both}
.hero.is-ready .hero__sub  {animation:rise .85s var(--expo) 1.22s both}
.hero.is-ready .hero__date {animation:rise .85s var(--expo) 1.38s both}
.hero.is-ready .cue        {animation:rise .85s var(--expo) 1.7s both}
/* two animations, sequenced: the float only starts once the plate has
   landed. Later in the list wins for `translate`, and plateIn ends at
   translate 0 anyway, so there is no jump between them. */
.hero.is-ready .hero__plate{
  animation:plateIn 1.1s var(--expo) .45s both,
            float 9s ease-in-out 1.8s infinite;
}

@keyframes rise{from{opacity:0;translate:0 22px}to{opacity:1;translate:0 0}}
@keyframes plateIn{
  from{opacity:0;translate:0 38px;scale:.94}
  to  {opacity:1;translate:0 0;   scale:1}
}
@keyframes float{0%,100%{translate:0 0}50%{translate:0 -11px}}
/* the inset bottom stays negative so descenders and the rotation are
   never clipped while the wipe runs */
@keyframes write{
  from{opacity:0;clip-path:inset(-30% 100% -30% -6%)}
  to  {opacity:1;clip-path:inset(-30% -6% -30% -6%)}
}

.hero__name{
  font-family:var(--display);font-style:italic;font-weight:500;
  font-size:clamp(1.5rem,4.4vw,2.3rem);
  margin:1.5rem 0 1.1rem;color:var(--pale);
}
.hero__sub{max-width:42ch;margin:0 0 1.8rem;opacity:.7}
.hero__date{
  display:inline-block;margin:0;color:var(--pale);
  font-size:.64rem;font-weight:600;letter-spacing:.22em;text-transform:uppercase;
  padding:.6rem 1.05rem;border-radius:99px;
  border:1px solid color-mix(in oklch,var(--wash) 45%,transparent);
}

.hero__plate{justify-self:center;max-width:min(370px,76vw)}
.plate__rings{color:var(--frost);opacity:.5;left:-26%;bottom:-6%;width:52%;z-index:2}

.cue{
  position:relative;z-index:1;align-self:center;
  margin-top:clamp(2.5rem,6vw,4rem);
  display:flex;align-items:center;gap:.7rem;text-decoration:none;opacity:.68;
  font-size:.62rem;font-weight:600;letter-spacing:.24em;text-transform:uppercase;
}
.cue i{width:1px;height:36px;background:currentColor;animation:drip 2.6s ease-in-out infinite}
@keyframes drip{0%,100%{scale:1 .3;transform-origin:top}50%{scale:1 1;transform-origin:top}}

/* =========================================================
   COSAS CIERTAS  —  laid out like a specimen sheet
   ========================================================= */
.about{position:relative;overflow:hidden;background:var(--prussian);padding:var(--sec-y) 0}
@media (min-width:1100px){.about{padding-left:var(--rail-w)}}
.about__stip{color:var(--pale);opacity:.24;right:-6%;top:5%;width:min(40vw,280px)}

.sheet{position:relative;z-index:1;display:grid;gap:clamp(2.5rem,6vw,5rem);align-items:start}
.sheet>*{min-width:0}
@media (min-width:880px){.sheet{grid-template-columns:1.3fr .7fr}}

/* Each entry is a two-column grid: the drawing sits in the left
   column spanning the whole row, like an illuminated initial, with
   the number, title and body stacked in the right column. */
.things{list-style:none;counter-reset:t;margin:0;padding:0}
.things li{
  counter-increment:t;position:relative;padding:1.9rem 0 2rem;
  border-top:1px solid color-mix(in oklch,var(--pale) 22%,transparent);
  display:grid;grid-template-columns:auto minmax(0,1fr);
  column-gap:clamp(.9rem,3vw,1.6rem);align-items:start;
}
.things li:last-child{border-bottom:1px solid color-mix(in oklch,var(--pale) 22%,transparent)}
@media (min-width:600px){.things li:nth-child(even){padding-left:clamp(1.5rem,5vw,3.5rem)}}
.things li::before{
  content:counter(t,decimal-leading-zero);grid-column:2;display:block;margin-bottom:.6rem;
  font-size:.64rem;font-weight:600;letter-spacing:.2em;color:var(--wash);
}
.thing__art{grid-column:1;grid-row:1 / -1;align-self:center}
.things h3{
  grid-column:2;
  font-family:var(--display);font-weight:700;font-optical-sizing:auto;
  font-size:clamp(1.3rem,3.4vw,1.85rem);line-height:1.14;
  margin:0 0 .55rem;text-wrap:balance;
}
.things p{grid-column:2;margin:0;opacity:.72;max-width:50ch;font-size:.98rem}

.about__plate{position:sticky;top:4rem;max-width:min(340px,72vw);justify-self:center}

.pull{position:relative;z-index:1;margin:clamp(4rem,10vw,7rem) 0 0;padding:0;text-align:center}
/* the trail drawing replaces the hairline that used to divide here */
.pull .art{margin:0 auto 1.6rem}
.pull p{
  font-family:var(--display);font-style:italic;font-weight:500;font-optical-sizing:auto;
  font-size:clamp(1.4rem,4.4vw,2.6rem);line-height:1.28;
  margin:0 auto;max-width:20ch;text-align:center;color:var(--frost);text-wrap:balance;
}

/* =========================================================
   LAS VOCES
   Cards as specimen labels. Each carries its own shape as a
   watermark, so no two read the same.
   ========================================================= */
.voices{position:relative;overflow:hidden;background:var(--ink);padding:var(--sec-y) 0}
@media (min-width:1100px){.voices{padding-left:var(--rail-w)}}
.voices__dome{color:var(--marine);opacity:.55;left:-10%;bottom:0;width:min(54vw,400px)}

.cards{
  position:relative;z-index:1;list-style:none;margin:0;padding:0;
  display:grid;gap:1.2rem;
  /* auto-fill, not auto-fit: auto-fit collapses the empty tracks, so a
     single card stretches the full width of the page and looks broken.
     auto-fill keeps the tracks, so one card sits at one card's width
     and the row fills up properly as more people send videos in. */
  grid-template-columns:repeat(auto-fill,minmax(min(100%,265px),1fr));
}
.card{
  position:relative;overflow:hidden;isolation:isolate;
  display:flex;flex-direction:column;gap:.75rem;
  width:100%;height:100%;text-align:left;cursor:pointer;
  padding:1.7rem 1.5rem 1.35rem;border:0;border-radius:14px 14px 4px 4px;
  background:var(--pale);color:var(--ink);font-family:inherit;
  box-shadow:0 12px 30px color-mix(in oklch,var(--ink) 55%,transparent);
  transition:translate .5s var(--expo),box-shadow .5s var(--expo);
}
.card--sky       {background:var(--pale)}
.card--cream     {background:var(--frost)}
/* --wash sits at L .615, a mid-tone: dark text on it starts at ~7:1
   and any opacity on a label drops it under AA. Lifted so the small
   caps have room to breathe, still distinct from --pale and --frost. */
.card--cornflower{background:oklch(0.758 0.058 234)}
.card--azure     {background:var(--marine);color:var(--frost)}

/* A fixed box with mask-size:contain, not an aspect-ratio, so every
   shape fits whole regardless of its own proportions. The arch is
   400x520; left to its own ratio it overflows the card and the top
   curve crops off, leaving what looks like a set of stripes. */
.card__bot{
  position:absolute;right:-6%;bottom:-8%;
  width:56%;height:76%;aspect-ratio:auto;z-index:-1;
  mask-size:contain;-webkit-mask-size:contain;
  mask-position:bottom right;-webkit-mask-position:bottom right;
  opacity:.14;transform-origin:85% 95%;
  transition:scale .7s var(--expo),opacity .7s var(--expo);
}
.card:hover,.card:focus-visible{
  translate:0 -6px;
  box-shadow:0 24px 48px color-mix(in oklch,var(--ink) 68%,transparent);
}
.card:hover .card__bot{scale:1.09;opacity:.2}

.card__role{margin:0;font-size:.63rem;font-weight:600;letter-spacing:.16em;text-transform:uppercase;opacity:.94}
.card__name{
  font-family:var(--display);font-weight:700;font-optical-sizing:auto;
  font-size:1.6rem;line-height:1.08;margin:0;
}

/* The line they said, given its own panel so it reads as a quote
   pinned to the card rather than more body copy. Asymmetric corners
   (sharp top-left, round bottom-right) keep it from looking like a
   default input box. */
.card__phrase{
  position:relative;margin:.15rem 0 0;
  padding:1.05rem 1.05rem 1.05rem 2.1rem;
  border:1px solid color-mix(in oklch,currentColor 22%,transparent);
  border-radius:2px 16px 2px 16px;
  background:color-mix(in oklch,currentColor 6%,transparent);
  font-family:var(--display);font-style:italic;
  font-size:1.04rem;line-height:1.45;
  transition:background .5s var(--expo),border-color .5s var(--expo);
}
.card__phrase::before{
  content:"\00AB";position:absolute;left:.7rem;top:.85rem;
  font-family:var(--display);font-weight:700;font-style:normal;
  font-size:1.5rem;line-height:1;opacity:.5;
}
.card:hover .card__phrase{
  background:color-mix(in oklch,currentColor 11%,transparent);
  border-color:color-mix(in oklch,currentColor 34%,transparent);
}
.card__foot{
  margin-top:auto;padding-top:1rem;display:flex;align-items:center;gap:.55rem;
  font-size:.62rem;font-weight:600;letter-spacing:.16em;text-transform:uppercase;
  border-top:1px solid color-mix(in oklch,currentColor 22%,transparent);
}
.card__play{
  width:24px;height:24px;border-radius:50%;flex:none;
  border:1px solid currentColor;display:grid;place-items:center;
}
.card__play::before{content:"";border-left:6px solid currentColor;border-block:4px solid transparent;margin-left:2px}
.card.is-locked{cursor:default;opacity:.88}
.card.is-locked:hover{translate:0 0;box-shadow:0 12px 30px color-mix(in oklch,var(--ink) 55%,transparent)}
.card.is-locked .card__play{border-style:dashed}
.card.is-locked .card__play::before{border:0;width:6px;height:6px;border-radius:50%;background:currentColor;margin:0}

/* =========================================================
   LA CARTA
   The one section that is not blue. After three screens of
   Prussian, warm paper reads as an actual letter.
   ========================================================= */
.letter{
  position:relative;overflow:hidden;
  background:var(--paper);color:var(--ink);padding:var(--sec-y) 0 0;
}
@media (min-width:1100px){.letter{padding-left:var(--rail-w)}}
.letter__peb{color:var(--prussian);opacity:.14;right:-5%;top:7%;width:min(38vw,270px)}

.letter__grid{position:relative;z-index:1;display:grid;gap:clamp(2.5rem,6vw,5rem);align-items:center}
.letter__grid>*{min-width:0}
@media (min-width:880px){.letter__grid{grid-template-columns:.75fr 1.25fr}}
.letter__plate{max-width:min(320px,72vw);justify-self:center}
.letter .plate__arch{box-shadow:0 26px 60px color-mix(in oklch,var(--prussian) 30%,transparent)}
.letter .plate__cap{opacity:.62}
.letter .eyebrow{opacity:.66}

.prose p{margin:0 0 1.2rem;max-width:62ch;opacity:.78}

/* the how-to-use-it line, lifted out of the prose so she can't miss it */
.note{
  margin:1.9rem 0 0;padding:1.1rem 1.3rem;max-width:54ch;
  border:1px dashed color-mix(in oklch,var(--prussian) 38%,transparent);
  border-radius:2px 14px 2px 14px;
  background:color-mix(in oklch,var(--prussian) 6%,transparent);
  font-size:.97rem;color:var(--prussian);
  display:flex;align-items:center;gap:1rem;
}
.note p{margin:0}
.art--note{width:clamp(44px,11vw,58px);aspect-ratio:1}

.sign{margin:2.6rem 0 0;display:flex;flex-direction:column;gap:.3rem}
.sign__off{
  font-family:var(--display);font-style:italic;font-weight:500;
  font-size:clamp(1.15rem,3vw,1.45rem);line-height:1.3;opacity:.85;
}
.sign__prefix{
  display:flex;align-items:center;gap:.1rem;flex-wrap:wrap;
  margin-top:.5rem;font-size:.86rem;opacity:.72;
}
.sign__name{
  font-family:var(--hand);font-weight:400;
  font-size:clamp(1.5rem,4.6vw,2.1rem);line-height:1.4;
  color:var(--prussian);rotate:-2deg;transform-origin:left center;
}

.foot{
  margin-top:clamp(4rem,10vw,7rem);padding:1.7rem var(--pad);
  border-top:1px solid color-mix(in oklch,var(--ink) 14%,transparent);
  text-align:center;font-size:.62rem;letter-spacing:.24em;text-transform:uppercase;opacity:.62;
}

/* =========================================================
   EL REPRODUCTOR
   What an NFC tap opens. Everything else defers to this.
   ========================================================= */
.player{
  position:fixed;inset:0;z-index:100;overflow:hidden auto;
  background:var(--ink);-webkit-overflow-scrolling:touch;
  padding:calc(env(safe-area-inset-top) + 1.25rem) var(--pad)
          calc(env(safe-area-inset-bottom) + 2.5rem);
  animation:develop .5s var(--expo);
}
.player[hidden]{display:none}
@keyframes develop{from{opacity:0;scale:1.012}to{opacity:1;scale:1}}
.player__bot{color:var(--marine);opacity:.38;right:-14%;top:-6%;width:min(48vw,330px)}

.player__inner{
  position:relative;z-index:1;max-width:740px;margin-inline:auto;
  display:flex;flex-direction:column;min-height:100%;
}
.player__close{
  align-self:flex-start;margin-bottom:clamp(1.8rem,6vw,3rem);
  display:flex;align-items:center;gap:.6rem;
  background:none;border:0;padding:.5rem .1rem;cursor:pointer;opacity:.55;
  font-size:.64rem;font-weight:600;letter-spacing:.2em;text-transform:uppercase;
  transition:opacity .3s var(--expo);
}
.player__close:hover{opacity:1}

.player__role{
  margin:0 0 .6rem;color:var(--wash);
  font-size:.63rem;font-weight:600;letter-spacing:.22em;text-transform:uppercase;
}
.player__name{
  font-family:var(--display);font-weight:900;font-optical-sizing:auto;
  font-size:clamp(2.3rem,10.5vw,4.2rem);line-height:.96;letter-spacing:-.02em;
  margin:0 0 clamp(1.5rem,5vw,2.4rem);
}
/* Matted to --ink rather than #000. Phone clips arrive at every aspect
   ratio, so object-fit:contain will letterbox or pillarbox something no
   matter what. Against black those bars read as a broken player; against
   the page colour they read as matting and disappear. */
.player__stage{
  border-radius:12px;overflow:hidden;background:var(--ink);
  box-shadow:0 26px 64px color-mix(in oklch,var(--ink) 80%,transparent);
}
.player__stage video{
  width:100%;height:auto;display:block;
  max-height:72svh;object-fit:contain;background:var(--ink);
}
.player__missing{
  padding:clamp(2.5rem,10vw,4rem) 1.5rem;text-align:center;
  background:var(--prussian);color:var(--pale);
  font-family:var(--display);font-style:italic;font-size:1.15rem;
}
/* The line they said. This is the whole reason the page exists, so it
   gets a panel of its own rather than sitting loose under the video:
   tinted ground, asymmetric corners matching the cards, an oversize
   ochre quote breaking the top edge, and one of the site's shapes
   watermarked into the corner. */
.player__quote{
  position:relative;overflow:hidden;isolation:isolate;
  margin:clamp(1.8rem,6vw,2.6rem) 0 0;
  padding:clamp(1.9rem,5.5vw,2.5rem) clamp(1.3rem,4vw,2rem) clamp(1.5rem,4vw,1.9rem);
  border:1px solid color-mix(in oklch,var(--wash) 32%,transparent);
  border-radius:3px 24px 3px 24px;
  background:color-mix(in oklch,var(--marine) 30%,transparent);
}
/* A guillemet, not a curly double quote. Bodoni draws " as two heavy
   ball terminals with almost no tail, which at display size reads as a
   colon rather than a quotation mark. « is an unmistakable chevron, and
   it is the correct opening quote in Spanish besides. */
.player__quote::before{
  content:"\00AB";position:absolute;left:1rem;top:.75rem;
  font-family:var(--display);font-weight:700;font-style:normal;
  font-size:clamp(2rem,7vw,2.6rem);line-height:1;
  color:var(--iron);opacity:.85;
}
.player__quoteBot{
  position:absolute;right:-8%;bottom:-22%;width:44%;height:130%;
  aspect-ratio:auto;z-index:-1;opacity:.13;color:var(--pale);
  mask-size:contain;-webkit-mask-size:contain;
  mask-position:bottom right;-webkit-mask-position:bottom right;
}
.player__quote p{
  font-family:var(--display);font-style:italic;font-weight:500;font-optical-sizing:auto;
  font-size:clamp(1.25rem,5vw,1.9rem);line-height:1.36;margin:0;text-wrap:pretty;
}
.player__attrib{
  margin-top:1.1rem;padding-top:.9rem;
  border-top:1px solid color-mix(in oklch,var(--wash) 26%,transparent);
  font-size:.64rem;font-weight:600;letter-spacing:.2em;text-transform:uppercase;
  color:var(--pale);
}

/* Something the person wrote, as opposed to said. Deliberately not
   styled like the spoken quote: no guillemet, a dashed rule instead of a
   solid panel, and the ochre label naming what it is. Receiving a written
   note is a different thing from hearing someone say it. */
.player__written{
  margin:clamp(1.1rem,4vw,1.6rem) 0 0;
  padding:clamp(1.1rem,4vw,1.4rem) clamp(1.1rem,4vw,1.5rem);
  border:1px dashed color-mix(in oklch,var(--wash) 40%,transparent);
  border-radius:16px 3px 16px 3px;
}
.player__written[hidden]{display:none}
/* Modo de un solo video: estas dos llevan display propio, así que
   [hidden] por sí solo no las apaga. */
.player__close[hidden],.player__pager[hidden],.voices[hidden]{display:none}
.player__writtenLabel{
  margin:0 0 .6rem;color:var(--iron);
  font-size:.62rem;font-weight:600;letter-spacing:.2em;text-transform:uppercase;
}
.player__writtenText{
  margin:0;color:var(--pale);
  font-family:var(--display);font-style:italic;font-weight:500;
  font-size:clamp(1rem,3.6vw,1.2rem);line-height:1.5;text-wrap:pretty;
}

.player__pager{margin-top:auto;padding-top:clamp(2.5rem,8vw,4rem);display:flex;justify-content:space-between;gap:1rem}
.ghost{
  background:none;cursor:pointer;color:var(--pale);border-radius:99px;
  border:1px solid color-mix(in oklch,var(--wash) 42%,transparent);
  padding:.72rem 1.25rem;
  font-size:.62rem;font-weight:600;letter-spacing:.18em;text-transform:uppercase;
  transition:background .35s var(--expo),border-color .35s var(--expo);
}
.ghost:hover:not(:disabled){background:color-mix(in oklch,var(--wash) 14%,transparent);border-color:var(--wash)}
.ghost:disabled{opacity:.22;cursor:default}

/* =========================================================
   LOS DIBUJITOS
   Seven small drawings. Each idles on its own so the page is
   alive at rest, and does something bigger on hover. Phones
   have no hover, so app.js adds .is-poked on tap and every
   hover rule below matches that too.
   ========================================================= */
.art{
  display:inline-flex;align-items:center;justify-content:center;
  flex:none;color:var(--wash);cursor:pointer;
  -webkit-tap-highlight-color:transparent;
  transition:color .5s var(--expo);
}
.art:hover,.art.is-poked{color:var(--frost)}
.art .ill{
  width:100%;height:100%;display:block;overflow:visible;
  fill:none;stroke:currentColor;stroke-width:2.4;
  stroke-linecap:round;stroke-linejoin:round;
}
.art *{transform-box:view-box}

.art--title{width:clamp(48px,11vw,70px);aspect-ratio:1;margin-left:.15em;vertical-align:-.18em}
.art--thing{width:clamp(42px,10vw,56px);aspect-ratio:1}
.art--quote{width:clamp(120px,30vw,190px);aspect-ratio:160/100;color:var(--iron);opacity:.9}
.art--sign {width:clamp(38px,9vw,46px);aspect-ratio:1;vertical-align:-.7em;margin-right:.1em}
.letter .art{color:var(--marine)}
.letter .art:hover,.letter .art.is-poked{color:var(--prussian)}

@keyframes art-spin{to{transform:rotate(360deg)}}

/* la tierra ------------------------------------------------ */
/* the land is laid down twice, 100 apart, and slides one full width
   before looping, so the seam never shows */
.ill--globe .g-land{animation:art-globe 26s linear infinite}
@keyframes art-globe{to{transform:translateX(-100px)}}
.ill--globe .g-par{opacity:.26;stroke-width:1.8}
.ill--globe .g-rim{stroke-width:2.6}
.art:hover .ill--globe .g-land,.art.is-poked .ill--globe .g-land{animation-duration:7s}

/* el teléfono tocando la placa ----------------------------- */
.ill--tap .t-waves path{opacity:0;animation:art-ping 2.4s ease-out infinite}
.ill--tap .w2{animation-delay:.28s}
.ill--tap .w3{animation-delay:.56s}
@keyframes art-ping{0%{opacity:0}22%{opacity:.95}70%{opacity:0}100%{opacity:0}}
.ill--tap .t-phone{transition:translate .5s var(--expo)}
.art:hover .ill--tap .t-phone,.art.is-poked .ill--tap .t-phone{translate:5px 0}
.art:hover .ill--tap .t-waves path,.art.is-poked .ill--tap .t-waves path{animation-duration:1s}

/* el corazón ----------------------------------------------- */
.ill--heart .h-beat{transform-origin:50px 56px;animation:art-beat 2.6s ease-in-out infinite}
@keyframes art-beat{
  0%,70%,100%{transform:scale(1)}
  10%{transform:scale(1.1)}22%{transform:scale(1)}32%{transform:scale(1.06)}
}
.ill--heart .h-ring{opacity:0;transform-origin:50px 54px;transform:scale(.66)}
.art:hover .ill--heart .h-ring,.art.is-poked .ill--heart .h-ring{animation:art-ring 1.3s var(--expo) infinite}
@keyframes art-ring{
  from{opacity:.5;transform:scale(.66)}to{opacity:0;transform:scale(1.3)}
}
.art:hover .ill--heart .h-beat,.art.is-poked .ill--heart .h-beat{animation-duration:.9s}

/* el sol derritiendo el glaciar ---------------------------- */
.ill--melt .m-rays{transform-origin:74px 24px;animation:art-spin 26s linear infinite}
.ill--melt .m-facet{opacity:.45}
.ill--melt .m-pool{opacity:.5;transform-origin:33px 78.5px;animation:art-pool 3.4s ease-in-out infinite}
@keyframes art-pool{0%,100%{transform:scaleX(.86)}50%{transform:scaleX(1)}}
.art:hover .ill--melt .m-pool,.art.is-poked .ill--melt .m-pool{animation-duration:1.3s;opacity:.8}
.ill--melt .drip{opacity:0;animation:art-drip 3.4s ease-in infinite}
.ill--melt .d2{animation-delay:1.1s}
.ill--melt .d3{animation-delay:2.2s}
@keyframes art-drip{
  0%{opacity:0;transform:translateY(-7px) scale(.6)}
  25%{opacity:.95;transform:translateY(-2px) scale(1)}
  100%{opacity:0;transform:translateY(15px) scale(.75)}
}
.art:hover .ill--melt .drip,.art.is-poked .ill--melt .drip{animation-duration:1.3s}
.art:hover .ill--melt .m-rays,.art.is-poked .ill--melt .m-rays{animation-duration:5s}

/* la puerta ------------------------------------------------ */
.ill--door .d-land,.ill--door .d-land2,.ill--door .d-sun{
  opacity:0;transition:opacity .7s var(--expo) .18s;
}
.ill--door .d-plank{opacity:.5}
.ill--door .d-panel{
  transform-origin:25px 88px;                 /* la bisagra */
  transition:transform 1s var(--expo);
  animation:art-ajar 7s ease-in-out infinite;
}
@keyframes art-ajar{0%,100%{transform:scaleX(1)}50%{transform:scaleX(.93)}}
.art:hover .ill--door .d-panel,.art.is-poked .ill--door .d-panel{
  animation:none;transform:scaleX(.09);
}
.art:hover .ill--door .d-land,.art:hover .ill--door .d-land2,.art:hover .ill--door .d-sun,
.art.is-poked .ill--door .d-land,.art.is-poked .ill--door .d-land2,.art.is-poked .ill--door .d-sun{
  opacity:1;
}

/* el sol --------------------------------------------------- */
.ill--sun .s-rays{transform-origin:50px 50px;animation:art-spin 34s linear infinite}
.ill--sun .s-core{transform-origin:50px 50px;animation:art-breathe 4.5s ease-in-out infinite}
@keyframes art-breathe{0%,100%{transform:scale(1)}50%{transform:scale(1.07)}}
.art:hover .ill--sun .s-rays,.art.is-poked .ill--sun .s-rays{
  animation-duration:7s;scale:1.14;
}
.ill--sun .s-rays{transition:scale .7s var(--expo)}

/* el sendero ----------------------------------------------- */
.ill--trail .t-path{stroke-dasharray:5 8;animation:art-march 3.2s linear infinite}
@keyframes art-march{to{stroke-dashoffset:-26}}
.art:hover .ill--trail .t-path,.art.is-poked .ill--trail .t-path{animation-duration:1.1s}

/* el osito ------------------------------------------------- */
.ill--bear .b-eyes{transform-origin:50px 50px;animation:art-blink 5.5s ease-in-out infinite}
@keyframes art-blink{0%,93%,100%{transform:scaleY(1)}96%{transform:scaleY(.08)}}
.ill--bear .b-head{transform-origin:50px 60px;transition:transform .6s var(--expo)}
.ill--bear .b-ear{transform-box:fill-box;transform-origin:center}
.art:hover .ill--bear .b-head,.art.is-poked .ill--bear .b-head{transform:rotate(-5deg)}
.art:hover .ill--bear .b-ear--l,.art.is-poked .ill--bear .b-ear--l{animation:art-wig .5s ease-in-out infinite}
.art:hover .ill--bear .b-ear--r,.art.is-poked .ill--bear .b-ear--r{animation:art-wig .5s ease-in-out infinite .12s}
@keyframes art-wig{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}

/* =========================================================
   REVEAL
   ========================================================= */
.reveal{opacity:0;translate:0 30px;transition:opacity .9s var(--expo),translate .9s var(--expo)}
.reveal.is-in{opacity:1;translate:0 0}

:focus-visible{outline:2px solid var(--iron);outline-offset:3px;border-radius:3px}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .reveal{opacity:1;translate:0 0;transition:none}
  .bot{animation:none !important;translate:none !important}
  .giant .ltr,body.is-loading .giant .ltr{opacity:1;animation:none}
  body.is-loading .hero__type > *,body.is-loading .hero__plate,body.is-loading .cue{opacity:1}
  .hero.is-ready .eyebrow,.hero.is-ready .script,.hero.is-ready .hero__name,
  .hero.is-ready .hero__sub,.hero.is-ready .hero__date,.hero.is-ready .cue,
  .hero.is-ready .hero__plate{animation:none;opacity:1;translate:0 0;scale:1;clip-path:none}
  .hero__type{translate:none !important;opacity:1 !important}
  .plate__img,.plate__arch{transition:none}
  /* the drawings hold still, but the door stays open so the
     landscape behind it is still reachable */
  .art *{animation:none !important;transition:none !important}
  .ill--door .d-panel{transform:scaleX(.09)}
  .ill--door .d-land,.ill--door .d-land2,.ill--door .d-sun{opacity:1}
  .cue i,.player{animation:none}
  .card,.rail a{transition:none}
}
