/* The atlas frame: the three slots, the plate, and the marks on it.

   The explorer's studio mounts the frame in a panel beside its canvas, and this file is
   loaded from there. It knows nothing about the page it is on, which is what let the
   standalone atlas page mount the same frame full bleed until
   `website_webp_and_atlas_deprecate` retired it; the frame's own size is `frame.js`.

   ## The four colours

   Blue is a place on the parameter plane and red is a place on a dynamical one, and that
   is the whole of the frame's colour language: the dots say it, the two fixed slots say it
   with a soft border of the same hue, and the gallery slot says which kind of place its
   picture came from with a deeper one. They are declared here rather than in `site.css`
   because they are not furniture — they are a reading of a record that exists on this
   page and nowhere else — and `builder/atlas.py` carries the same two dot values for the
   figure section 11 shows, because Pillow cannot read CSS.

   They sit on the frame itself rather than on a page's body, and on the one line outside
   it that spends them: `.place-key`, the Atlas tab's note naming the two kinds in the two
   hues. That key was the retired atlas page's intro, and it moved into the tab rather than
   going with the page *(atlas_page_deprecate_and_wakelock_ckpt141)*, because a reader who
   cannot tell the blue marks from the red has lost half of what the plate says.

   The soft borders are mixed toward the well's own rule colour rather than declared
   separately, so there is one hue per kind and the "soft" and "deeper" ends of it are
   derived from the same token. */

.frame,
.place-key {
  --place-mandelbrot: #4d8df0;
  --place-julia: #f2584c;
  --edge-mandelbrot: #2f6bc4;
  --edge-julia: #c4372c;
}

.place-key .key-mandelbrot { color: var(--place-mandelbrot); font-weight: 600; }
.place-key .key-julia { color: var(--place-julia); font-weight: 600; }

/* ------------------------------------------------------------------------- the frame

   One fixed frame, and it never moves. The strip and the plate are sized once, in pixels,
   by `frame.js` from the box its host gives; nothing here depends on which mark is under
   the pointer, and there is no text inside the frame that could reflow when one is. What
   the captions used to say is a `title` on the slot, because a tooltip is drawn over the
   page rather than in it.

   The strip spans the plate exactly — three slots and two gaps, the same gap again
   between the strip and the plate — so the two are one composed rectangle rather than a
   row of pictures above a picture.

   `frame.js` puts `.frame-host` on whatever element it was handed and takes it off again
   at `destroy`: a frame is centred in its box without either page having to say so, and
   the box is the host's rather than the window's, which is the whole of the difference
   between the retired atlas page's stage and the studio's panel. */
.frame-host {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
}
.frame-host[hidden] { display: none; }

.frame { flex: 0 0 auto; }

/* The strip of planes, and the line under the plate. Both sit outside the fitted
   rectangle and both change only when a reader moves to another plane — never under the
   pointer — which is what lets the frame go on being the one fixed thing it is. `refit`
   takes their height off the box before it divides, so they cost the plate room rather
   than pushing it out of the panel. */
.planes {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.25rem;
  font-family: var(--sans);
}

/* **A chip is read, not glanced at.** It was set at 0.75rem with the degree in a raised
   glyph, which put the one character that tells `z³` from `z⁶` at around 7px on a desktop
   window: the strip looked like a row of identical pills. The chip is now a shade over the
   tab strip the studio hangs the frame under, which is the smallest control text this
   project sets, and the exponent is a `sup` sized below. */
.plane {
  appearance: none;
  border: 1px solid var(--well-rule);
  border-radius: 999px;
  background: none;
  color: var(--well-ink-dim);
  font: inherit;
  font-size: 0.9375rem;
  line-height: 1.5;
  padding: 0.05rem 0.7rem;
  cursor: pointer;
  white-space: nowrap;
}
.plane:hover { color: var(--well-ink); border-color: var(--well-ink-dim); }
.plane[aria-pressed="true"] {
  color: var(--well);
  background: var(--well-ink);
  border-color: var(--well-ink);
}
.plane:focus-visible { outline: 2px solid var(--well-link); outline-offset: 1px; }

/* A chip with a miniature of its plate beside its label, which only the article asks for.
   The picture sits inside the pill's left end, so the padding that side is the pill's
   border radius rather than the text's air; the chip grows about a third taller and is a
   better thing to tap for it. On a phone column the strip wraps to two rows. */
.plane.has-miniature {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.15rem 0.7rem 0.15rem 0.2rem;
}
/* Two classes deep, because an article page's `.figure img` sizes every picture in a figure
   to the figure's width and outranks one class. */
.plane .plane-miniature {
  display: block;
  flex: 0 0 auto;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 0.3rem;
}

/* `.slot img` sets a display of its own, so the browser's `[hidden]` no longer wins: an
   empty slot's picture is hidden by a rule of the frame's instead. */
.frame [hidden] { display: none !important; }

.strip { display: flex; justify-content: space-between; font-size: 0; }

/* A page that puts a control of its own beside each slot wraps the slot in a cell, which
   takes the slot's place in the strip and is what the control is positioned against. */
.slot-cell { position: relative; display: block; flex: 0 0 auto; }

.slot {
  position: relative;
  display: block;
  flex: 0 0 auto;
  background: var(--well);
  border: 1px solid var(--well-rule);
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
}
.slot img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* A slot is its own container, so that its label can be sized against the slot rather than
   the page. At the widths the studio's panel and a desktop column give, the cap below is
   what binds and nothing changes; on a phone's column a slot is under a hundred pixels,
   and *Mandelbrot* at the kicker's spacing ran off its right edge (atlas_live_ckpt146). */
.slot { container-type: inline-size; }

/* A frame that hands its picks back to the page it is in rather than opening the explorer
   builds its slots as buttons, so that they are still reachable from the keyboard without
   an href to be reached by. A button brings a browser's own furniture with it, and none of
   it is wanted: the slot is a picture with a border. */
button.slot { margin: 0; padding: 0; font: inherit; color: inherit; cursor: pointer; }

/* The two fixed slots always say what they are; the gallery slot has no kind until a mark
   is under the pointer, and takes the well's own rule until it has one. */
.slot[data-slot="mandelbrot"] {
  border-color: color-mix(in srgb, var(--place-mandelbrot) 55%, var(--well-rule));
}
.slot[data-slot="julia"] {
  border-color: color-mix(in srgb, var(--place-julia) 55%, var(--well-rule));
}
.slot.from-mandelbrot { border-color: var(--edge-mandelbrot); }
.slot.from-julia { border-color: var(--edge-julia); }

.slot:focus-visible { outline: 2px solid var(--well-ink); outline-offset: -3px; }

/* A label on the top edge of the picture, not a row above it: a row is a height, and a
   height is something that can change. The site's kicker treatment, centred the way every
   short label under a picture on this site is centred, over a scrim that fades out so it
   reads on a bright render and a black one alike.

   It carries two things: the plane's name, and — on the two location slots — the map the
   engine iterates there. The label sits on the picture rather than in the layout, so a map
   too long for a narrow slot wraps to a second line and moves nothing; on a plate at full
   bleed both sit on one. */
.slot-label {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  padding: 0.55em 0.6em 1.2em;
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.78),
    rgba(0, 0, 0, 0.42) 55%,
    rgba(0, 0, 0, 0)
  );
  color: var(--well-ink);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
  font-family: var(--sans);
  font-size: min(0.8125rem, 11cqi);
  line-height: 1.3;
  text-align: center;
  pointer-events: none;
}

/* **The uppercasing stops at the name.** A formula's case is its meaning — `z` is the
   orbit and `c` the constant, and neither is a `Z` or a `C` — so the kicker treatment is
   the name's alone and the map is set as the mathematics it is. */
.slot-name {
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
/* **The map is a line of its own, and it is never broken.** Under the name rather than
   beside it, because a slot is a third of a plate and the plate is whatever the host is:
   set inline, Phoenix's three terms wrapped at whichever `+` fell at the edge in a studio
   panel and sat on one line on a wide plate, so the same header had two shapes and one of
   them broke a formula in half. Stacked and `nowrap`, every header reads the same way at
   every width, and the slot with no map — the gallery — is a name on one line as before. */
/* **And it is set at the name's size, not a caption's.** The two used to share a font
   size, which is not the same as reading alike: the name is uppercase, so its every letter
   stands at cap height, while the map is lowercase mathematics whose `z` and `c` sit at
   the x-height — a good third shorter — with the exponent smaller again. Set a step above
   the name, the two lines read as one header rather than as a title with a footnote. */
.slot-map {
  display: block;
  letter-spacing: normal;
  text-transform: none;
  white-space: nowrap;
  font-size: 1.15em;
  color: var(--well-ink-dim);
}

/* An index the page sets rather than the font: big enough to read at the sizes this
   frame's text runs at, and shifted without `super`'s claim on the line's height, because
   the strip's height is taken off the plate and a line that grew would cost a picture. */
.plane sup,
.plane sub,
.slot-map sup,
.slot-map sub {
  font-size: 0.72em;
  line-height: 0;
  vertical-align: baseline;
  position: relative;
}
.plane sup,
.slot-map sup { top: -0.45em; }
.plane sub,
.slot-map sub { top: 0.22em; }

.plate {
  position: relative;
  background: var(--well);
  border: 1px solid var(--well-rule);
}
.plate > img { display: block; width: 100%; height: 100%; }

/* --------------------------------------------------------------------------- the marks

   Blue for a place on the parameter plane, red for a place on a dynamical one. The plate
   is grey and mostly dark, so every dot carries a thin light outline: a dot with no edge
   disappears into the bright filaments and doubles in the black.

   The hit area is bigger than the dot, which is what makes 150 of them usable with a
   mouse; the dot itself is what changes size, so growing one does not move the pointer
   off it. */
.mark {
  position: absolute;
  width: 18px;
  height: 18px;
  margin: -9px 0 0 -9px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  display: grid;
  place-items: center;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.mark::before {
  content: "";
  display: block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.72), 0 0 2px 1px rgba(0, 0, 0, 0.55);
  transition: width 90ms ease-out, height 90ms ease-out;
}
.mark-mandelbrot::before { background: var(--place-mandelbrot); }
.mark-julia::before { background: var(--place-julia); }

.mark:hover::before,
.mark:focus-visible::before {
  width: 15px;
  height: 15px;
  filter: brightness(1.3);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.95), 0 0 6px 2px rgba(0, 0, 0, 0.5);
}
.mark:focus-visible { outline: none; }
