/*
  button-dawn: the horizon button.

  A capsule of night sky with a low horizon across it. The sun is the knob: it carries the arrow and
  sits half risen out of the water on the right. The label is in the sky, a time kicker lies in the
  water under it like a reflection. At rest it is the minute before dawn: stars wink, a rose glow lies
  along the horizon, rays turn slowly behind the sun, the sun's road shimmers on the water, a spark
  runs the horizon to the sun, and now and then the arrow sinks into the sea and the next one drops in.
  Pointed at or focused, LIGHT FLOODS UP through the sky from the horizon, the stars go out and the
  sun climbs. Pressed (the go state, set by the host), the light SURGES UP out of the top of the
  capsule, a ring breaks off the sun, and the capsule SPLITS ALONG ITS HORIZON: the sky lifts off the
  sea and the gap between them is light that shoots past both ends. A page that lifts a section on
  the press can hang a .button-dawn-seam on that section's bottom edge, and the same light opens
  along it.

  CSS does all of the drawing and all of the motion. button-dawn.js is optional: the host's hold
  class, pausing off screen, where the seam opens from, and a landed event. See README.md.

  THEMING. The block below is every colour, face, size and timing this component takes from its host,
  declared at zero specificity (:where), so a page that declares the same names wins without
  !important, on :root or on any ancestor of the button. Every mix of two tokens is built on the
  element that paints it, never up here: a custom property that reads another one is resolved where
  it is DECLARED, so a mix on :root would freeze at the root's colours and ignore a palette set on a
  section (button-dusk's trap 1, the same here).

  --button-dawn-paint-* is a different tier: the component and its script write those (lit, go, the
  seam's starting point). Setting one by hand does nothing useful.
*/
:where(:root) {
  /* the sky, top to horizon */
  --button-dawn-night: #0A1130;
  --button-dawn-indigo: #1D1B50;
  --button-dawn-violet: #4A2A6E;
  /* the dawn, horizon up: what floods in */
  --button-dawn-rose: #B23F6A;
  --button-dawn-ember: #F07A3A;
  --button-dawn-gold: #FFB547;
  --button-dawn-light: #FFF3DA;        /* the sun's core, the horizon under the sun, the split, the seam, the stars */
  --button-dawn-water: #070B20;        /* under the horizon */
  /* words, arrow, ring */
  --button-dawn-text: #FFFFFF;
  --button-dawn-kicker: #FFC98A;
  --button-dawn-arrow: #2B1338;        /* on the sun */
  --button-dawn-focus: #A1520B;        /* the keyboard ring; it sits on the HOST's background */
  --button-dawn-shadow: #10192E;       /* the drop shadow, cast on the host's background */
  /* faces. Hand the component yours: these defaults are only what any machine has. */
  --button-dawn-font-display: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --button-dawn-font-mono: ui-monospace, "Cascadia Mono", Consolas, monospace;
  --button-dawn-stretch: 108%;         /* the label's width axis; ignored by a face without one */
  /* size */
  --button-dawn-height: 70px;          /* the capsule's least height; the sun's centre sits half of it in from the right */
  --button-dawn-sun-size: 50px;        /* the knob */
  --button-dawn-water-depth: 20px;     /* the horizon's height above the bottom edge; the kicker lies in it */
  --button-dawn-min-width: 340px;
  --button-dawn-max-width: 520px;
  --button-dawn-flare: 84px;           /* how far the split's light shoots past each end */
  /* time */
  --button-dawn-cycle: 6.4s;           /* one pass of the spark, the stars, the glow's breath and the arrow */
  --button-dawn-spin: 64s;             /* one turn of the rays */
  --button-dawn-flood-time: 760ms;     /* the light flooding up on hover and focus */
  --button-dawn-go-time: 1200ms;       /* the surge. A plain time in ms or s, not calc(): the script reads it too */
}

/* ---------- the capsule ----------
   Stacking, back to front: the surge (behind everything, so it shows only above the capsule), the
   sky, the sun, the sea (IN FRONT of the sun: that is what makes it half risen), the split, the kicker,
   and the label over all of it. */

.button-dawn {
  /* the two switches every layer reads. lit: pointed at, focused, or going. go: going. */
  --button-dawn-paint-lit: 0;
  --button-dawn-paint-go: 0;
  /* a <button> brings its own face and border; an <a> its underline */
  -webkit-appearance: none; appearance: none; margin: 0; border: 0; background: none; font: inherit;
  position: relative; isolation: isolate; box-sizing: border-box;
  display: inline-flex; align-items: center; gap: 30px;
  min-height: var(--button-dawn-height);
  min-width: min(var(--button-dawn-min-width), 100%);
  /* both limits: 100% for a narrow column, 100vw - 32px for a full-bleed one on a phone (button-dusk trap 2) */
  max-width: min(var(--button-dawn-max-width), 100%, 100vw - 32px);
  /* the sun sits as far in from the right as it does from the top, so its centre is half the height in */
  /* 6px top and bottom do nothing to a one-line label; a wrapped one keeps clear of the stars */
  padding: 6px calc((var(--button-dawn-height) - var(--button-dawn-sun-size)) / 2) 6px 30px;
  border-radius: 999px;
  color: var(--button-dawn-text); text-decoration: none; text-align: left; cursor: pointer;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
  vertical-align: middle;
  translate: 0 calc(var(--button-dawn-paint-lit) * -2px);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--button-dawn-shadow) 30%, transparent),
    0 18px 30px -18px color-mix(in srgb, var(--button-dawn-shadow) 90%, transparent),
    0 14px 36px -14px color-mix(in srgb, var(--button-dawn-ember) 34%, transparent);
  transition: translate .5s cubic-bezier(.2, .8, .2, 1), box-shadow .7s ease, scale .14s ease;
}
.button-dawn:focus-visible, .button-dawn[data-button-dawn-go] { --button-dawn-paint-lit: 1; }
/* hover only where the pointer hovers: a phone keeps :hover after a tap, and the button would still
   be lit when the reader comes back up to it */
@media (hover: hover) {
  .button-dawn:hover {
    --button-dawn-paint-lit: 1;
    box-shadow:
      0 0 0 1px color-mix(in srgb, var(--button-dawn-gold) 40%, transparent),
      0 22px 34px -18px color-mix(in srgb, var(--button-dawn-shadow) 90%, transparent),
      0 16px 46px -10px color-mix(in srgb, var(--button-dawn-ember) 62%, transparent);
  }
}
.button-dawn:focus-visible, .button-dawn[data-button-dawn-go] {
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--button-dawn-gold) 40%, transparent),
    0 22px 34px -18px color-mix(in srgb, var(--button-dawn-shadow) 90%, transparent),
    0 16px 46px -10px color-mix(in srgb, var(--button-dawn-ember) 62%, transparent);
}
.button-dawn[data-button-dawn-go] { --button-dawn-paint-go: 1; }
.button-dawn:active { scale: .985; }
.button-dawn:focus-visible { outline: 3px solid var(--button-dawn-focus); outline-offset: 5px; }
.button-dawn:focus:not(:focus-visible) { outline: none; }

/* ---------- the sky ----------
   The air is a slab from the top to the horizon. Going, it lifts and the sky's own background, light,
   shows in the gap it leaves (the split). At rest that background is transparent, so no light can
   bleed round the curved ends while the capsule is shut. */
.button-dawn-sky, .button-dawn-sea {
  position: absolute; inset: 0; border-radius: inherit; overflow: hidden; pointer-events: none;
}
.button-dawn-sky { z-index: -1; background-color: transparent; }
.button-dawn[data-button-dawn-go] .button-dawn-sky { background-color: var(--button-dawn-light); }

.button-dawn-air {
  position: absolute; left: 0; right: 0; top: 0; bottom: var(--button-dawn-water-depth); overflow: hidden;
  background: linear-gradient(180deg, var(--button-dawn-night), var(--button-dawn-indigo) 54%,
    color-mix(in srgb, var(--button-dawn-violet) 78%, var(--button-dawn-rose)) 100%);
  translate: 0 calc(var(--button-dawn-paint-go) * -2.5px);
  transition: translate .45s cubic-bezier(.2, .8, .2, 1);
}

/* stars: two sets that wink in turn, and go out as the light comes. They keep to the strip above the
   label, so no star ever lands on a letter and reads as punctuation (README, trap 3). */
.button-dawn-stars {
  position: absolute; inset: 0;
  opacity: calc(1 - var(--button-dawn-paint-lit));
  transition: opacity .55s ease;
}
.button-dawn-stars::before, .button-dawn-stars::after {
  content: ""; position: absolute; inset: 0;
  animation: button-dawn-twinkle var(--button-dawn-cycle) ease-in-out infinite;
}
.button-dawn-stars::before {
  background:
    radial-gradient(circle at 14% 7px, var(--button-dawn-light) 0 .8px, transparent 1.5px),
    radial-gradient(circle at 37% 10px, var(--button-dawn-light) 0 .6px, transparent 1.2px),
    radial-gradient(circle at 58% 5px, var(--button-dawn-light) 0 .9px, transparent 1.6px),
    radial-gradient(circle at calc(100% - var(--button-dawn-height) * .9) 9px, var(--button-dawn-light) 0 .6px, transparent 1.2px);
}
.button-dawn-stars::after {
  animation-delay: calc(var(--button-dawn-cycle) / -2);
  background:
    radial-gradient(circle at 25% 5px, var(--button-dawn-light) 0 .7px, transparent 1.4px),
    radial-gradient(circle at 47% 8px, var(--button-dawn-light) 0 .8px, transparent 1.5px),
    radial-gradient(circle at 70% 11px, var(--button-dawn-light) 0 .5px, transparent 1.1px);
}
@keyframes button-dawn-twinkle { 0%, 100% { opacity: .3; } 50% { opacity: 1; } }

/* the flood: the dawn, held below the horizon at rest with only its rose edge showing, raised into
   the sky when lit. Its colours step down to rose well below the words, so white type keeps its
   contrast at every point of the rise (README, trap 2). */
.button-dawn-flood {
  position: absolute; inset: 0;
  background:
    radial-gradient(21% 92% at calc(100% - var(--button-dawn-height) / 2) 100%,
      color-mix(in srgb, var(--button-dawn-gold) 92%, transparent) 0,
      color-mix(in srgb, var(--button-dawn-ember) 62%, transparent) 30%,
      color-mix(in srgb, var(--button-dawn-rose) 28%, transparent) 62%, transparent 100%),
    linear-gradient(0deg,
      color-mix(in srgb, var(--button-dawn-ember) 74%, var(--button-dawn-rose)) 0,
      color-mix(in srgb, var(--button-dawn-rose) 80%, transparent) 16%,
      color-mix(in srgb, var(--button-dawn-rose) 44%, transparent) 42%,
      color-mix(in srgb, var(--button-dawn-violet) 34%, transparent) 72%, transparent 100%);
  translate: 0 calc((1 - var(--button-dawn-paint-lit)) * 56%);
  transition: translate var(--button-dawn-flood-time) cubic-bezier(.22, .8, .24, 1);
  animation: button-dawn-breathe var(--button-dawn-cycle) ease-in-out infinite;
}
@keyframes button-dawn-breathe { 0%, 100% { opacity: .78; } 50% { opacity: 1; } }

/* rays: a slow fan behind the sun, clipped at the horizon by the air, and fainter on the label's side
   of the sun: lit, they sweep over the brightest part of the flood, and a bright ray passing behind the
   end of the label took its worst-pixel contrast from 5.5 to 4.0 (README, trap 2) */
.button-dawn-rays {
  position: absolute; width: 240px; aspect-ratio: 1; border-radius: 50%;
  right: calc(var(--button-dawn-height) / 2); top: calc(50% + var(--button-dawn-water-depth) / 2);
  translate: 50% -50%;
  background: repeating-conic-gradient(color-mix(in srgb, var(--button-dawn-gold) 75%, transparent) 0deg 2.5deg, transparent 2.5deg 13deg);
  -webkit-mask: radial-gradient(closest-side, #000 18%, transparent 100%), linear-gradient(90deg, rgba(0, 0, 0, .12) 30%, #000 50%);
  -webkit-mask-composite: source-in;
  mask: radial-gradient(closest-side, #000 18%, transparent 100%), linear-gradient(90deg, rgba(0, 0, 0, .12) 30%, #000 50%);
  mask-composite: intersect;
  opacity: calc(.3 + var(--button-dawn-paint-lit) * .38);
  scale: calc(1 + var(--button-dawn-paint-lit) * .28);
  animation: button-dawn-spin var(--button-dawn-spin) linear infinite;
  transition: opacity .7s ease, scale .9s cubic-bezier(.2, .8, .2, 1);
}
@keyframes button-dawn-spin { to { rotate: 360deg; } }

/* ---------- the sea: in front of the sun ---------- */
.button-dawn-sea { z-index: 3; }
.button-dawn-water {
  position: absolute; left: 0; right: 0; bottom: 0; height: var(--button-dawn-water-depth);
  /* a little see-through at the top, so the sun's lower edge shows under the surface */
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--button-dawn-rose) 20%, transparent), transparent 70%),
    linear-gradient(180deg, color-mix(in srgb, color-mix(in srgb, var(--button-dawn-water) 70%, var(--button-dawn-violet)) 80%, transparent),
      color-mix(in srgb, var(--button-dawn-water) 96%, transparent) 60%);
  translate: 0 calc(var(--button-dawn-paint-go) * 2px);
  transition: translate .45s cubic-bezier(.2, .8, .2, 1);
}
/* the warm water as the light comes up */
.button-dawn-water::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(40% 140% at calc(100% - var(--button-dawn-height) / 2) 0,
    color-mix(in srgb, var(--button-dawn-ember) 45%, transparent), transparent 100%);
  opacity: calc(.35 + var(--button-dawn-paint-lit) * .65);
  transition: opacity .7s ease;
}
/* the sun's road: short dashes of light in a wedge under the sun, widening toward the viewer, in two
   sets that glint in turn and drift. Drawn dash by dash: a repeating pattern lines its dashes up into
   columns and reads as a bar chart. */
.button-dawn-glitter {
  position: absolute; top: 1px; bottom: 0; width: 124px;
  right: calc(var(--button-dawn-height) / 2); translate: 50% 0;
  -webkit-mask: linear-gradient(90deg, transparent, #000 30%, #000 70%, transparent);
  mask: linear-gradient(90deg, transparent, #000 30%, #000 70%, transparent);
  opacity: calc(.6 + var(--button-dawn-paint-lit) * .4);
  transition: opacity .6s ease;
}
.button-dawn-glitter::before, .button-dawn-glitter::after {
  content: ""; position: absolute; inset: 0;
  animation: button-dawn-shimmer 2.2s ease-in-out infinite;
}
.button-dawn-glitter::before {
  background:
    linear-gradient(var(--button-dawn-light), var(--button-dawn-light)) 57px 1px / 9px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 50px 4px / 6px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 67px 4px / 7px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 44px 7px / 8px 1px no-repeat,
    linear-gradient(var(--button-dawn-light), var(--button-dawn-light)) 59px 7px / 4px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 72px 7px / 9px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 36px 10px / 7px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 53px 10px / 10px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 78px 10px / 7px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 28px 13px / 10px 1px no-repeat,
    linear-gradient(var(--button-dawn-light), var(--button-dawn-light)) 60px 13px / 8px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 86px 13px / 9px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 20px 16px / 7px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 44px 16px / 10px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 72px 16px / 8px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 95px 16px / 8px 1px no-repeat;
}
.button-dawn-glitter::after {
  animation-delay: -1.1s;
  background:
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 61px 2px / 5px 1px no-repeat,
    linear-gradient(var(--button-dawn-light), var(--button-dawn-light)) 56px 5px / 4px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 72px 5px / 5px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 40px 8px / 6px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 55px 8px / 9px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 80px 8px / 5px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 46px 11px / 6px 1px no-repeat,
    linear-gradient(var(--button-dawn-light), var(--button-dawn-light)) 66px 11px / 9px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 88px 11px / 5px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 34px 14px / 8px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 52px 14px / 4px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 74px 14px / 9px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 98px 14px / 6px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 26px 17px / 9px 1px no-repeat,
    linear-gradient(var(--button-dawn-light), var(--button-dawn-light)) 58px 17px / 11px 1px no-repeat,
    linear-gradient(var(--button-dawn-gold), var(--button-dawn-gold)) 88px 17px / 8px 1px no-repeat;
}
@keyframes button-dawn-shimmer { 0%, 100% { opacity: 1; translate: 0 0; } 50% { opacity: .2; translate: 2px 0; } }

/* the horizon: a hairline along the top of the water, brightest under the sun */
.button-dawn-horizon {
  position: absolute; left: 0; right: 0; top: 0; height: 1px;
  background: linear-gradient(90deg, transparent 2%,
    color-mix(in srgb, var(--button-dawn-gold) 40%, transparent) 24%,
    var(--button-dawn-gold) calc(100% - var(--button-dawn-height) * 1.5),
    var(--button-dawn-light) calc(100% - var(--button-dawn-height) / 2),
    color-mix(in srgb, var(--button-dawn-gold) 55%, transparent) 97%, transparent);
  opacity: calc(.72 + var(--button-dawn-paint-lit) * .28);
  transition: opacity .6s ease;
}
/* the spark that runs the horizon to the sun once a cycle */
.button-dawn-glint {
  position: absolute; left: 0; right: calc(var(--button-dawn-height) / 2); top: -3px; height: 7px; overflow: hidden;
}
.button-dawn-glint::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(closest-side, var(--button-dawn-light), color-mix(in srgb, var(--button-dawn-gold) 50%, transparent) 50%, transparent) right center / 56px 100% no-repeat;
  translate: -100% 0; opacity: 0;
  animation: button-dawn-glint var(--button-dawn-cycle) cubic-bezier(.45, 0, .3, 1) infinite;
}
@keyframes button-dawn-glint {
  0%, 36% { translate: -100% 0; opacity: 0; }
  42% { opacity: 1; }
  74% { translate: 0 0; opacity: 1; }
  84%, 100% { translate: 0 0; opacity: 0; }
}

/* ---------- the words ---------- */

.button-dawn-label {
  /* above every glow (the sun's, the bloom, the split): light goes BEHIND the words, never over them */
  position: relative; z-index: 6; flex: 1 1 auto; min-width: 0;
  /* centred in the sky, not the whole capsule: the horizon is low. The 6px margins, with the capsule's
     6px padding, keep a wrapped label out of the star strip (README, trap 3) without moving a
     one-line label any nearer the bright horizon. */
  margin: 6px 0 calc(var(--button-dawn-water-depth) + 6px);
  font-family: var(--button-dawn-font-display); font-stretch: var(--button-dawn-stretch);
  font-size: 19px; font-weight: 700; line-height: 1.15; letter-spacing: -.004em;
  color: var(--button-dawn-text); text-wrap: balance;
  /* a close dark halo: the words stay crisp on any part of the dawn behind them */
  text-shadow: 0 1px 2px color-mix(in srgb, var(--button-dawn-night) 75%, transparent),
    0 0 8px color-mix(in srgb, var(--button-dawn-night) 45%, transparent),
    0 0 18px color-mix(in srgb, var(--button-dawn-night) 35%, transparent);
}
/* the words' shade: night held across the middle of the sky, where the words are, so white type keeps
   its contrast while the dawn floods and the flash goes off. Without it the worst single pixel behind
   the letters read 3.35:1 with the rays frozen at their worst angle (README, trap 2).

   It is the CAPSULE's own ::before at z-index 1, not a pool behind the label: above the whole sky
   (z -1 and everything in it) and UNDER the sun (2), the water (3) and the words (6). That is what
   keeps it from reading as a dark plate. It runs the full length of the capsule and is widest where
   the words are, so it has no edge of its own anywhere a reader can see one: the end nearest the sun
   goes under the sun, the ends under the water, and the rest fades into the night it is made of.
   Nothing at rest (the night behind the words is already dark), up with the flood, full while going. */
.button-dawn::before {
  content: ""; position: absolute; z-index: 1; inset: 0; border-radius: inherit; pointer-events: none;
  /* 35% tall, centred at 36%: it reaches nothing by 71% of the height, which is the horizon, so the
     water keeps its own light, and nothing at the top, so the stars keep their sky */
  background: radial-gradient(135% 35% at 52% 36%,
    color-mix(in srgb, var(--button-dawn-night) 82%, transparent) 0,
    color-mix(in srgb, var(--button-dawn-night) 60%, transparent) 44%,
    color-mix(in srgb, var(--button-dawn-night) 26%, transparent) 74%, transparent 100%);
  opacity: calc(var(--button-dawn-paint-lit) * .72 + var(--button-dawn-paint-go) * .28);
  transition: opacity var(--button-dawn-flood-time) cubic-bezier(.22, .8, .24, 1);
}
/* the kicker lies on the water under the label, like its reflection */
.button-dawn-kicker {
  position: absolute; z-index: 5; left: 31px; bottom: 0; height: var(--button-dawn-water-depth);
  max-width: calc(100% - 31px - var(--button-dawn-height) * 1.6); overflow: hidden;
  display: flex; align-items: center;
  font: 500 10px/1 var(--button-dawn-font-mono); letter-spacing: .2em; text-transform: uppercase;
  color: var(--button-dawn-kicker); white-space: nowrap;
  translate: 0 calc(var(--button-dawn-paint-go) * 2px);
  /* going, the light off the split washes over the water: the reflection fades rather than sit
     unreadable in the glare */
  opacity: calc(1 - var(--button-dawn-paint-go));
  transition: translate .45s cubic-bezier(.2, .8, .2, 1), opacity .3s ease;
}

/* ---------- the sun: the knob ---------- */

.button-dawn-sun {
  position: relative; z-index: 2; flex: none;
  width: var(--button-dawn-sun-size); height: var(--button-dawn-sun-size); border-radius: 50%;
  translate: 0 calc(var(--button-dawn-paint-lit) * -5px + var(--button-dawn-paint-go) * -4px);
  transition: translate .7s cubic-bezier(.2, .8, .2, 1);
}
/* its glow, breathing. A box shadow, not a bigger box: a shadow is ink, so it can reach past a
   phone's edge without scrolling the page sideways (README, trap 1). */
.button-dawn-sun::before {
  content: ""; position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
  box-shadow: 0 0 16px 4px color-mix(in srgb, var(--button-dawn-gold) 55%, transparent),
    0 0 32px 8px color-mix(in srgb, var(--button-dawn-ember) 24%, transparent);
  opacity: calc(.6 + var(--button-dawn-paint-lit) * .4);
  animation: button-dawn-pulse var(--button-dawn-cycle) ease-in-out infinite;
  transition: opacity .6s ease;
}
@keyframes button-dawn-pulse { 0%, 100% { opacity: calc(.45 + var(--button-dawn-paint-lit) * .45); } 50% { opacity: 1; } }
.button-dawn-disc {
  position: absolute; inset: 0; border-radius: 50%; overflow: hidden;
  display: grid; place-items: center;
  background: radial-gradient(circle at 50% 30%, var(--button-dawn-light) 0,
    color-mix(in srgb, var(--button-dawn-gold) 70%, var(--button-dawn-light)) 24%,
    var(--button-dawn-gold) 50%, var(--button-dawn-ember) 100%);
  box-shadow:
    inset 0 -4px 7px color-mix(in srgb, var(--button-dawn-ember) 75%, transparent),
    inset 0 1px 1px var(--button-dawn-light),
    0 0 0 1px color-mix(in srgb, var(--button-dawn-light) 30%, transparent),
    0 0 18px 2px color-mix(in srgb, var(--button-dawn-gold) 50%, transparent);
}
/* before dawn the sun is redder: a tint that lifts off when lit */
.button-dawn-disc::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: linear-gradient(180deg, color-mix(in srgb, var(--button-dawn-ember) 30%, transparent),
    color-mix(in srgb, var(--button-dawn-rose) 60%, transparent));
  opacity: calc(1 - var(--button-dawn-paint-lit));
  transition: opacity .6s ease;
}
/* two arrows. Once a cycle the first sinks into the sea while the second drops in from above, so
   there is always an arrow in the sun; the loop restarts on the same picture it ended on. Going, the
   same handover runs once, quickly, and also ends on the rest picture, so letting go cannot cut. */
.button-dawn-disc svg {
  grid-area: 1 / 1; position: relative; width: 22px; height: 22px; max-width: none;
  fill: none; stroke: var(--button-dawn-arrow); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round;
}
.button-dawn-disc svg:first-of-type { animation: button-dawn-sink var(--button-dawn-cycle) infinite; }
.button-dawn-disc svg + svg { translate: 0 -170%; animation: button-dawn-follow var(--button-dawn-cycle) infinite; }
@keyframes button-dawn-sink {
  0%, 82% { translate: 0 0; animation-timing-function: cubic-bezier(.55, 0, .75, .3); }
  96%, 100% { translate: 0 170%; }
}
@keyframes button-dawn-follow {
  0%, 84% { translate: 0 -170%; animation-timing-function: cubic-bezier(.2, .75, .3, 1); }
  100% { translate: 0 0; }
}
.button-dawn[data-button-dawn-go] .button-dawn-disc svg:first-of-type { animation: button-dawn-out .4s cubic-bezier(.55, 0, .8, .2) both; }
.button-dawn[data-button-dawn-go] .button-dawn-disc svg + svg { animation: button-dawn-in .5s .22s cubic-bezier(.2, .8, .3, 1) both; }
@keyframes button-dawn-out { from { translate: 0 0; } to { translate: 0 170%; } }
@keyframes button-dawn-in { from { translate: 0 -170%; } to { translate: 0 0; } }

/* ---------- the go state's light ----------
   Everything that reaches past the capsule is INK, never layout: box shadows, an outline, a blur.
   Ink can spread past a phone's edge without scrolling the page sideways; a box that is merely
   transparent cannot (the first surge column was 150px wide and an invisible 22px of it hung off a
   390px screen at rest; README, trap 1). The checks measure scrollWidth at rest, lit and going. */

/* the ring that breaks off the sun: an outline growing away from it */
.button-dawn-ring {
  position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
  outline: 2px solid color-mix(in srgb, var(--button-dawn-gold) 80%, var(--button-dawn-ember)); outline-offset: 0;
  opacity: 0;
}
.button-dawn[data-button-dawn-go] .button-dawn-ring { animation: button-dawn-ring calc(var(--button-dawn-go-time) * .7) cubic-bezier(.15, .7, .3, 1); }
@keyframes button-dawn-ring { 0% { opacity: 1; outline-offset: 0; outline-width: 3px; } 100% { opacity: 0; outline-offset: 46px; outline-width: 1px; } }

/* the bloom: a warm glow thrown up off the sun onto whatever is above the button */
.button-dawn-sun::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
  box-shadow: 0 -26px 56px 22px color-mix(in srgb, var(--button-dawn-gold) 62%, transparent),
    0 -46px 110px 46px color-mix(in srgb, var(--button-dawn-ember) 30%, transparent);
  opacity: 0;
}
.button-dawn[data-button-dawn-go] .button-dawn-sun::after { animation: button-dawn-bloom var(--button-dawn-go-time) cubic-bezier(.2, .7, .2, 1); }
@keyframes button-dawn-bloom { 0% { opacity: 0; } 16% { opacity: 1; } 100% { opacity: 0; } }

/* motes: sparks of light that rise off the sun. Two little dots, each throwing three more as box
   shadows, climbing at two speeds. */
.button-dawn-motes { position: absolute; left: 50%; top: 50%; width: 0; height: 0; pointer-events: none; }
.button-dawn-motes::before, .button-dawn-motes::after {
  content: ""; position: absolute; left: -1.5px; top: -1.5px; width: 3px; height: 3px; border-radius: 50%;
  background: var(--button-dawn-light);
  box-shadow: 0 0 6px 1px var(--button-dawn-gold),
    -16px 10px 0 -.4px var(--button-dawn-light), -16px 10px 6px 1px color-mix(in srgb, var(--button-dawn-gold) 80%, transparent),
    14px 18px 0 -.6px var(--button-dawn-gold), 14px 18px 5px 1px color-mix(in srgb, var(--button-dawn-ember) 70%, transparent),
    -6px 30px 0 -.2px var(--button-dawn-light), -6px 30px 6px 1px color-mix(in srgb, var(--button-dawn-gold) 70%, transparent);
  opacity: 0;
}
.button-dawn-motes::after { left: 4px; top: 6px; scale: -1 1; }
.button-dawn[data-button-dawn-go] .button-dawn-motes::before { animation: button-dawn-rise var(--button-dawn-go-time) cubic-bezier(.15, .6, .3, 1); }
.button-dawn[data-button-dawn-go] .button-dawn-motes::after { animation: button-dawn-rise calc(var(--button-dawn-go-time) * 1.2) .08s cubic-bezier(.15, .6, .3, 1) backwards; }
@keyframes button-dawn-rise {
  0% { opacity: 0; translate: 0 10px; }
  14% { opacity: 1; }
  100% { opacity: 0; translate: 0 -150px; }
}

/* the sky flashes white-hot round the sun as it goes, then settles to the lit dawn */
.button-dawn-air::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(24% 120% at calc(100% - var(--button-dawn-height) / 2) 100%,
    var(--button-dawn-light), color-mix(in srgb, var(--button-dawn-gold) 70%, transparent) 34%, transparent 72%);
  opacity: 0;
}
.button-dawn[data-button-dawn-go] .button-dawn-air::after { animation: button-dawn-flash var(--button-dawn-go-time) cubic-bezier(.2, .7, .2, 1); }
@keyframes button-dawn-flash { 0% { opacity: 0; } 14% { opacity: .85; } 100% { opacity: 0; } }

/* the split's light, along the horizon and past both ends like a lens flare */
.button-dawn-flare {
  position: absolute; z-index: 4; left: 4px; right: 4px; bottom: var(--button-dawn-water-depth); height: 2px; translate: 0 50%;
  border-radius: 2px; pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--button-dawn-light) 12%, var(--button-dawn-light) 88%, transparent);
  box-shadow:
    0 0 6px 1px var(--button-dawn-light),
    0 0 14px 3px color-mix(in srgb, var(--button-dawn-gold) 85%, transparent),
    calc(-.5 * var(--button-dawn-flare)) 0 5px -.5px color-mix(in srgb, var(--button-dawn-light) 85%, transparent),
    calc(.5 * var(--button-dawn-flare)) 0 5px -.5px color-mix(in srgb, var(--button-dawn-light) 85%, transparent),
    calc(-1 * var(--button-dawn-flare)) 0 10px -1px color-mix(in srgb, var(--button-dawn-gold) 60%, transparent),
    var(--button-dawn-flare) 0 10px -1px color-mix(in srgb, var(--button-dawn-gold) 60%, transparent),
    0 0 11px 1px color-mix(in srgb, var(--button-dawn-ember) 40%, transparent);
  opacity: 0;
  transition: opacity .5s ease;
}
.button-dawn[data-button-dawn-go] .button-dawn-flare {
  opacity: .85;
  animation: button-dawn-split var(--button-dawn-go-time) cubic-bezier(.2, .8, .2, 1);
}
@keyframes button-dawn-split {
  0% { opacity: 0; scale: .1 1; }
  24% { opacity: 1; scale: 1.04 1.8; }
  100% { opacity: .85; scale: 1 1; }
}

/* the surge: a pillar of light that leaves through the top of the capsule, wide at the sun and
   narrowing as it climbs. It is BEHIND the sky, so it shows only above the top edge. The shape is
   drawn on the pseudo-elements and blurred by the box, so the blur softens the shape's edges; the
   box itself is no wider than the sun's place. */
.button-dawn-beam {
  position: absolute; z-index: -2; pointer-events: none;
  right: calc(var(--button-dawn-height) * .06); bottom: 50%;
  width: calc(var(--button-dawn-height) * .88); height: 260px;
  filter: blur(6px);
  transform-origin: 50% 100%;
  opacity: 0;
}
.button-dawn-beam::before, .button-dawn-beam::after { content: ""; position: absolute; inset: 0; }
.button-dawn-beam::before {
  clip-path: polygon(34% 0, 66% 0, 100% 100%, 0 100%);
  background: linear-gradient(0deg, var(--button-dawn-light), color-mix(in srgb, var(--button-dawn-gold) 90%, transparent) 16%,
    color-mix(in srgb, var(--button-dawn-ember) 52%, transparent) 46%, color-mix(in srgb, var(--button-dawn-rose) 18%, transparent) 74%, transparent 96%);
}
.button-dawn-beam::after {
  left: 44%; right: 44%;
  background: linear-gradient(0deg, var(--button-dawn-light) 0, var(--button-dawn-light) 30%, transparent 92%);
}
.button-dawn[data-button-dawn-go] .button-dawn-beam {
  animation: button-dawn-surge var(--button-dawn-go-time) cubic-bezier(.2, .7, .2, 1);
}
@keyframes button-dawn-surge {
  0% { opacity: 0; scale: .7 .08; }
  14% { opacity: 1; }
  55% { opacity: .9; scale: 1 1; }
  100% { opacity: 0; scale: 1.1 1.16; }
}

/* ---------- the seam: optional, on the section that lifts ----------
   A <span class="button-dawn-seam" aria-hidden="true"> as a DIRECT child of a positioned section
   that holds the button. When the button goes, a line of light opens along the section's bottom edge
   from under the sun outward, glowing up onto the section and spilling below it, so as the section
   lifts it lifts off light. :has() finds the pair with no script; button-dawn.js only says where
   along the edge to start. */
.button-dawn-seam { position: absolute; z-index: 6; left: 0; right: 0; bottom: 0; height: 0; pointer-events: none; }
.button-dawn-seam::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--button-dawn-gold) 85%, transparent) 6%,
    var(--button-dawn-light) var(--button-dawn-paint-seam-x, 50%),
    color-mix(in srgb, var(--button-dawn-gold) 85%, transparent) 94%, transparent);
  box-shadow: 0 0 8px 1px var(--button-dawn-light),
    0 0 18px 3px color-mix(in srgb, var(--button-dawn-gold) 80%, transparent),
    0 -14px 44px 6px color-mix(in srgb, var(--button-dawn-ember) 34%, transparent);
  transform-origin: var(--button-dawn-paint-seam-x, 50%) 50%;
  scale: 0 1; opacity: 0;
  transition: scale .3s ease, opacity .5s ease;
}
.button-dawn-seam::after {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 96px;
  background: radial-gradient(60% 100% at var(--button-dawn-paint-seam-x, 50%) 0,
    color-mix(in srgb, var(--button-dawn-gold) 60%, transparent),
    color-mix(in srgb, var(--button-dawn-ember) 22%, transparent) 46%, transparent 100%);
  opacity: 0;
  transition: opacity .6s ease;
}
:where(:has(> .button-dawn-seam):has(.button-dawn[data-button-dawn-go])) > .button-dawn-seam::before {
  scale: 1 1; opacity: 1;
  transition: scale 1.1s cubic-bezier(.2, .8, .2, 1) .1s, opacity .2s ease .1s;
}
:where(:has(> .button-dawn-seam):has(.button-dawn[data-button-dawn-go])) > .button-dawn-seam::after {
  opacity: 1; transition: opacity .8s ease .2s;
}

/* ---------- off screen: frozen where it is, and carries on when it comes back ----------
   Not while going: the surge is a one-off the host may be waiting on (button-dawn:landed). */
.button-dawn[data-button-dawn-off]:not([data-button-dawn-go]) *,
.button-dawn[data-button-dawn-off]:not([data-button-dawn-go]) *::before,
.button-dawn[data-button-dawn-off]:not([data-button-dawn-go]) *::after { animation-play-state: paused; }

/* ---------- holding still ----------
   One composed frame for a paused button and for reduced motion: both star sets lit, the rays and the
   road fixed, the rose glow along the horizon at full breath, the sun's glow full, no spark, the arrow
   at rest in the sun. Lit, the light is up at once; going, the finished go frame at once: the sky
   parted, the split lit, the seam open, no surge and no ring (those are travel, and their last frame
   is nothing). animation: none rather than a paused play state, so the frame is the same every time.
   [data-button-dawn-paused] is written by button-dawn.js (the host's hold class, or pause()), or by
   you in the markup. Hover and focus still answer while paused: they are replies, not motion. */
.button-dawn[data-button-dawn-paused],
/* the capsule's OWN ::before (the words' shade) is not a descendant: `* ::before` misses it, and its
   transition went on running under the hold class until the check caught it */
.button-dawn[data-button-dawn-paused]::before,
.button-dawn[data-button-dawn-paused]::after,
.button-dawn[data-button-dawn-paused] *,
.button-dawn[data-button-dawn-paused] *::before,
.button-dawn[data-button-dawn-paused] *::after { animation: none !important; transition: none !important; }
:where(:has(> .button-dawn-seam):has(.button-dawn[data-button-dawn-paused])) > .button-dawn-seam::before,
:where(:has(> .button-dawn-seam):has(.button-dawn[data-button-dawn-paused])) > .button-dawn-seam::after { transition: none; }
@media (prefers-reduced-motion: reduce) {
  .button-dawn,
  .button-dawn::before,
  .button-dawn::after,
  .button-dawn *,
  .button-dawn *::before,
  .button-dawn *::after,
  .button-dawn-seam::before,
  .button-dawn-seam::after { animation: none !important; transition: none !important; }
}

/* ---------- forced colours ----------
   The drawing is put away: a plain outlined capsule, the words, and the arrow in a ringed disc. */
@media (forced-colors: active) {
  .button-dawn { border: 2px solid ButtonText; box-shadow: none; }
  .button-dawn-sky, .button-dawn-sea, .button-dawn-beam, .button-dawn-flare, .button-dawn-ring, .button-dawn-seam,
  .button-dawn-sun::before, .button-dawn-sun::after, .button-dawn-motes, .button-dawn-disc::before,
  .button-dawn::before { display: none; }
  .button-dawn-label { margin-bottom: 0; }
  .button-dawn-kicker { display: none; }
  .button-dawn-disc { background: none; box-shadow: none; border: 2px solid ButtonText; }
  .button-dawn-disc svg { stroke: ButtonText; }
  .button-dawn:focus-visible { outline-color: Highlight; }
}

/* ---------- paper ----------
   ON PAPER THE SKY IS THE PAPER. This used to hide only the surge's layers and then force the rest of
   the colour through (print-color-adjust: exact), so a printed page carried 322x70px of dark navy and
   orange with a white label on it, which no reader can drop the background of (2026-10-10 review). The
   night, the water and the sun's glow go; what is left is what the button SAYS: the label, the time
   under it and the arrow, in the paper's own ink inside a hairline capsule. The system colours are the
   same answer the forced-colours block above gives, for the same reason. */
@media print {
  .button-dawn {
    background: none; box-shadow: none; color: CanvasText;
    border: 1px solid currentColor; translate: none;
  }
  .button-dawn-sky, .button-dawn-sea, .button-dawn-beam, .button-dawn-flare, .button-dawn-ring,
  .button-dawn-motes, .button-dawn-seam, .button-dawn-sun::before, .button-dawn-sun::after,
  .button-dawn-disc::before, .button-dawn::before { display: none; }
  .button-dawn-label, .button-dawn-kicker { color: CanvasText; opacity: 1; translate: none; }
  .button-dawn-disc { background: none; box-shadow: none; border: 1px solid currentColor; }
  .button-dawn-disc svg { stroke: currentColor; animation: none; translate: 0; }
  .button-dawn-disc svg + svg { display: none; }
}
