/* ==========================================================================
   Three-dimensional structure figures.

   The furniture is the report's own: `.figure`, `.figure__frame`,
   `.figure__legend`, `.controls` and `.seg` all come from components.css and
   are not restated here. What this file adds is the stage the viewer draws
   into, the descriptions that stand for the structures whether or not a scene
   is ever drawn, and the reset button, which is the one control the filter
   bars do not already have.

   Two states, and the difference between them is one attribute the script sets
   once it has a working viewer. Without it the figure is a short reference
   list: every structure the figure could show, described, with its resolution
   and a link to its databank entry, and no empty box above them. With it the
   list narrows to whichever structure is on the stage. No prose is hidden by
   the `hidden` attribute here, because prose hidden that way is prose a reader
   without a script would lose, and the only thing they are meant to lose is
   the rotation. The two elements that do ship hidden — the colour key and the
   line explaining a scene that failed — carry no fact of their own and mean
   nothing without a scene, and both are given an explicit `[hidden]` rule
   below, because a class from components.css otherwise outranks the user
   agent's and leaves them on screen.

   The stage is white. A structure viewer's default is black, and black is the
   colour of a game, not of a page that means to look like a figure in a
   journal and to survive being printed.
   ========================================================================== */

.structure { margin: var(--s-7) 0; }

.structure__heading {
  font-family: var(--font-display);
  font-size: var(--step-2);
  line-height: var(--lh-snug);
  letter-spacing: -0.01em;
  color: var(--ink-strong);
  margin: 0 0 var(--s-2);
}

.structure__frame { padding: var(--s-5); }

/* --- Controls -----------------------------------------------------------
   Built by the script and only ever present when there is a viewer under
   them, so there is no disabled state to write here: a figure that cannot be
   drawn has no controls at all rather than dead ones. `.controls` brings the
   row and the hairline under it. */
.structure__controls { align-items: baseline; margin-bottom: var(--s-4); }

.structure__reset {
  font: inherit;
  font-size: var(--step--1);
  padding: 0.24rem 0.75rem;
  border: 1px solid var(--rule);
  /* Not a capsule. The filters elsewhere on the page stopped being pills
     because a rounded tinted capsule is the badge shape and reads as a label
     the document is applying rather than a control the reader is holding. A
     reset is a different kind of control — an action, not a state — so it
     keeps its outline where the filters lost theirs, and it takes the same 5px
     the search field takes, because those two are the page's only bordered
     controls and there is no reason for them to disagree about a corner. */
  border-radius: 5px;
  background: var(--card);
  color: var(--ink-3);
  cursor: pointer;
  white-space: nowrap;
  margin-left: auto;
  align-self: center;
  transition: color var(--dur-1) var(--ease-out),
              border-color var(--dur-1) var(--ease-out);
}
.structure__reset:hover { color: var(--ink); border-color: var(--connector); }
.structure__reset:active { color: var(--accent-ink); border-color: var(--accent); }

/* One focus treatment for every part of the figure that takes focus, drawn in
   the azure focus colour rather than the brand green, so the browser's
   position marker can never be mistaken for a pressed state. */
.structure__controls button:focus-visible,
.structure__canvas:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* The hint sits on its own line under the row. It is written by the script and
   describes gestures, so it exists only where those gestures do. */
.structure__hint {
  flex-basis: 100%;
  margin: var(--s-2) 0 0;
  font-size: var(--step--2);
  line-height: var(--lh-body);
  color: var(--ink-4);
}

/* --- Stage ---------------------------------------------------------------
   Absent until the script says otherwise. A box reserved for a scene that
   never arrives is the failure this whole arrangement is built to avoid, so
   the space is taken at the moment a viewer is known to be openable and not
   one paint earlier. */
.structure__stage { display: none; }

.structure[data-structure-live] .structure__stage {
  display: block;
  position: relative;
  /* Held to a shape rather than to a height, so the scene is the same
     composition on a phone as on a desk. The cap is on the width: three by two
     at 690px is 460 tall, which is a figure on the page rather than a screen
     of its own. */
  aspect-ratio: var(--structure-aspect, 3 / 2);
  width: 100%;
  max-width: 690px;
  margin-inline: auto;
  overflow: hidden;
  border-radius: 6px;
  /* Not quite white: a hair of tint, so the pale end of the protein and the
     page behind it stay distinguishable at the rim of the scene. */
  background: #FCFDFD;
  border: 1px solid var(--rule);
}

.structure__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
/* The viewer positions its own canvas absolutely inside the mount point; this
   keeps it off the rounded corner while it settles. */
.structure__canvas canvas { display: block; border-radius: 6px; }

/* While the library and the coordinates are in flight the stage is empty, and
   an empty white box with a border reads as something broken. A quiet wash
   says it is on its way, and it is a wash of the page's own sunk paper rather
   than a spinner, because a spinner over a figure that takes 200ms is more
   movement than information. */
.structure[data-structure-live] .structure__stage[data-structure-state="loading"] {
  background: var(--paper-sunk);
}

/* --- The line that appears when the scene could not be drawn -------------
   Only ever seen after a viewer opened and then failed. A hairline and a
   sentence: no tinted panel, because a failure the reader can do nothing about
   should not be the loudest thing on the page. */
.structure__why {
  margin: 0 0 var(--s-4);
  padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--rule);
  font-size: var(--step--1);
  line-height: var(--lh-body);
  color: var(--ink-3);
  max-width: 68ch;
}

/* --- Legend --------------------------------------------------------------
   A key to the colours in the scene, so it appears with the scene and goes
   with it. */
.structure__legend { margin-top: var(--s-4); }

/* Two elements in this figure ship with the `hidden` attribute and are
   unhidden by the script: the legend, when a scene has been drawn, and the
   line saying why there is none, when one was attempted and failed. Both
   inherit a `display` from a class in components.css, and a class beating the
   user agent's `[hidden] { display: none }` is how a hidden element stays on
   screen. The legend did: on a machine with no graphics context the page
   showed a key to four colours in a scene that was never drawn, which is the
   one thing this figure is built not to do. So the attribute is honoured here,
   at a specificity the class rules cannot outrank. It is deliberately written
   against the attribute rather than against a state class, because `hidden` is
   what the markup ships and what the script toggles. */
.structure__legend[hidden],
.structure__why[hidden] { display: none; }

/* The same trap one level down. `.figure__legend span` sets `inline-flex` on
   every item, so a key item the script puts away for a structure that has no
   such colour on the stage would stay on screen without this. */
.structure__legend span[hidden] { display: none; }
/* Atoms are round. A square swatch beside a stick model reads as a chart key
   borrowed from the wrong figure. */
.structure__legend .swatch { width: 11px; height: 11px; border-radius: 50%; }

/* --- The structures, in words -------------------------------------------
   Without a viewer this is the figure: every structure it could have shown,
   in the order the switch would have offered them, separated by the page's
   hairline. With a viewer it is one description at a time, under the scene. */
.structure__entries { margin-top: var(--s-4); }

.structure__entry + .structure__entry {
  margin-top: var(--s-4);
  padding-top: var(--s-4);
  border-top: 1px solid var(--rule);
}

.structure__entry-title {
  margin: 0 0 var(--s-1);
  font-family: var(--font-display);
  font-size: var(--step-0);
  font-weight: 600;
  line-height: var(--lh-snug);
  color: var(--ink-strong);
}

.structure__entry-meta {
  margin: 0 0 var(--s-2);
  font-size: var(--step--2);
  line-height: var(--lh-body);
  color: var(--ink-4);
}
.structure__entry-link { color: var(--ink-3); }
.structure__entry-link:hover { color: var(--link); }

.structure__entry-body {
  margin: 0;
  font-size: var(--step--1);
  line-height: var(--lh-body);
  color: var(--ink-2);
  max-width: 68ch;
}

/* One at a time once the switch exists. Keyed off an attribute rather than the
   `hidden` one: `hidden` is the page's promise that a reader without a script
   still sees the words, and these are put away precisely because a script is
   running. */
.structure[data-structure-live] .structure__entry[data-structure-off] { display: none; }
.structure[data-structure-live] .structure__entry + .structure__entry {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}
/* With the scene above it, the description is one entry rather than a list, so
   it takes the hairline that separates it from the picture instead of the ones
   that separated it from its neighbours. */
.structure[data-structure-live] .structure__entries {
  margin-top: var(--s-4);
  padding-top: var(--s-4);
  border-top: 1px solid var(--rule);
}

/* --- Print ---------------------------------------------------------------
   A canvas prints as a bitmap at whatever the screen gave it, which at this
   size is a soft grey smear. The scene is dropped and every structure's own
   description is printed instead, which is the same trade the page makes for a
   reader whose browser cannot draw one. */
@media print {
  .structure__controls,
  .structure__stage,
  .structure__legend { display: none !important; }
  .structure[data-structure-live] .structure__entry[data-structure-off] { display: block; }
  .structure[data-structure-live] .structure__entries {
    margin-top: var(--s-4);
    padding-top: 0;
    border-top: 0;
  }
  .structure[data-structure-live] .structure__entry + .structure__entry {
    margin-top: var(--s-4);
    padding-top: var(--s-4);
    border-top: 1px solid var(--rule);
  }
}
