/* The size figure's stylesheet, loaded after calc.css by the two places that
 * draw one: /size, which asks for it in its head, and the calculator, which
 * asks for it the first time an answer compares two areas and never otherwise.
 *
 * A second file, for the reasons sun.css and clocks.css each give. Inline is
 * refused outright by the policy in public/_headers, which has no
 * 'unsafe-inline' in style-src. Folded into calc.css it would ride along on
 * every visit from everybody who never asks how big anything is.
 *
 * What is not here is everything calc.css already says: the tokens, the body
 * rule, .wrap, .sr, .nav and .foot are the sheet next door's, and two copies of
 * a token is one token that will be changed in one place.
 */

/* ===== THE TWO FILLS =====
 *
 * The container is the ground and the item is the thing laid on it, and the
 * picture works only if a reader can tell in one glance which is which. The
 * ground is quiet and the overlay is not, which is the same direction the
 * clock board's ramp runs and needs no key for the same reason.
 *
 * Both pairs were measured rather than eyeballed. The overlay on the ground is
 * 4.9:1 in light and 5.4:1 in dark, which clears AA for a shape this size with
 * room to spare, and the overlay's own edge is drawn as well as filled so it
 * survives being three pixels across at 238 to one.
 */
.size {
  --ground: #dbe3ec;
  --ground-line: #b6c3d4;
  --laid: #d1604a;
  --laid-line: #a8402c;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .size {
    --ground: #2a323d;
    --ground-line: #3d4855;
    --laid: #e07a63;
    --laid-line: #f0a48f;
  }
}
:root[data-theme="dark"] .size {
  --ground: #2a323d;
  --ground-line: #3d4855;
  --laid: #e07a63;
  --laid-line: #f0a48f;
}

/* ===== HOW WIDE THE FIGURE IS =====
 *
 * One number, --size-w, which is how many CSS pixels the DRAWING may be. The
 * figure writes it onto the mount when the reader pulls an edge or presses a
 * bracket, and takes it off again when they press reset, so an untouched
 * figure is whatever this sheet says it is and is not pinned to a number by
 * having been measured.
 *
 * Two places read it, and they are the same fact said twice:
 *
 *   the svg      never draws wider than --size-w, and keeps the viewBox's own
 *                640 to 420, so the height follows the width and is never
 *                dragged apart from it;
 *   the box      is the column, or the drawing plus its own border and
 *                padding once that is wider than the column, and the negative
 *                margin either side is what lets it break out of a 672-pixel
 *                column and stay centred in the window while it does.
 *
 * The figure clamps --size-w against the viewport's own width less a gutter,
 * so the box's edges are always inside the window and the page never gains a
 * sideways scrollbar. That clamp is arithmetic and lives in src/size.js where
 * the suite can reach it; this sheet only spends the number.
 *
 * Nothing here can touch the ratio the picture claims. The shapes are laid out
 * in a fixed 640 by 420 viewBox at one scale for both, and a wider frame draws
 * that same viewBox at more pixels to the unit.
 */
.size {
  --size-chrome: 1.125rem;   /* one border and two paddings, in the width */
  --size-box: max(100%, calc(var(--size-w, 0px) + var(--size-chrome)));
  box-sizing: border-box;
  width: var(--size-box);
  margin-left: calc((100% - var(--size-box)) / 2);
  margin-right: calc((100% - var(--size-box)) / 2);
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--chip);
  padding: 0.5rem;
  /* The figure takes focus as a group so the arrows can move the overlay. The
   * svg inside it is aria-hidden: it is an illustration of a sentence that is
   * already on the page, and reading two polygons out would be noise.
   */
  outline-offset: 2px;
}
.size:focus-visible { outline: 2px solid var(--text); }
/* ...and no ring for the reader who arrived by pointer, which the clock
   board argued first and for the same reason: a ring says where the keyboard
   is, Chrome hands :focus-visible to anything focused from script, and this
   figure is focused from script by the press that picks the shape up. The
   pointer says so on the way in and the first key takes it back off. */
.size[data-by="pointer"]:focus-visible { outline: none; }

/* The drawing and the two strips that pull it wider, in a box of their own so
 * that the strips run down the drawing and not down the bar underneath it,
 * where the pair of pickers already reaches both edges.
 */
.size__stage { position: relative; }

.size__svg {
  display: block;
  width: 100%;
  /* ...and never wider than the reader asked for, centred in whatever is left.
   * height:auto with a fixed viewBox is the whole of "the height follows the
   * width": there is no second number and nothing to drag vertically.
   */
  max-width: var(--size-w, none);
  margin-left: auto;
  margin-right: auto;
  height: auto;
  /* The page keeps the vertical swipe until there is a frame to move.
   *
   * touch-action: none here was the whole figure taking every gesture, and at
   * fit there is nothing for a one-finger drag to do: the frame is pinned to
   * the ground and the pan is inert by construction. So a thumb anywhere on a
   * figure a third of a phone screen tall produced nothing and stopped the
   * page scrolling as well. Once the reader has stood closer there is somewhere
   * to go, and the gesture is worth taking. The shape itself is always ours.
   */
  touch-action: pan-y;
}

.size__into-fill {
  fill: var(--ground);
  stroke: var(--ground-line);
  stroke-width: 1;
  stroke-linejoin: round;
  /* Not scaled with the frame either, for the reason the overlay gives below
   * and one of its own: the zoom's whole return is the coastline it uncovers,
   * and a stroke that grew with it would be 16px of rounded-off line at the
   * far end, drawn half outside the shape, hiding exactly what was zoomed into.
   */
  vector-effect: non-scaling-stroke;
}

.size__of {
  cursor: grab;
  transition: filter 120ms ease;
  touch-action: none;      /* the shape's drag is ours in both figures */
}
/* The thing a finger presses, sized in the figure rather than here: never
 * smaller than 44px across whatever the shape under it has shrunk to. Invisible
 * and unfilled, so it has to be told to take a press at all.
 */
.size__grab { fill: none; pointer-events: all; }
.size--dragging .size__of { cursor: grabbing; }
.size__of-fill {
  fill: var(--laid);
  stroke: var(--laid-line);
  /* Drawn as well as filled, so a shape three pixels across is still a shape.
   * Not scaled with the drawing: at 238 to one the stroke is most of what is
   * left of the silhouette, and that is the honest picture of 1/238.
   */
  stroke-width: 1.25;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.size--dragging .size__of { filter: brightness(1.08); }

/* ===== THE TWO EDGES =====
 *
 * A strip down each side of the drawing that says the frame can be pulled, and
 * says it the way the request asked for: by being hovered. Nothing is drawn
 * until a pointer is somewhere near, because an affordance drawn all the time
 * is a second border round a figure that already has one, on both halves of
 * every ratio answer.
 *
 * Two steps of showing. Approaching the drawing at all brings the pair up
 * faintly, which is what stops the control being a secret; landing on one
 * brings it up fully and turns the cursor, which is what says this one is
 * live. The mark inside is half the height of the drawing and two pixels wide,
 * so it reads as an edge to take hold of rather than as part of the picture.
 *
 * Twelve pixels wide against a drawing 366 or 654 across, at the two sides
 * where there is least worth panning to. That is the whole of what the frame's
 * own drag gives up for this.
 */
.size__edge {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 12px;
  cursor: ew-resize;
  opacity: 0;
  transition: opacity 120ms ease;
  /* The pull is ours from the first pixel: without this a finger that found
   * the strip would scroll the page instead, and a pointercancel would land in
   * the middle of the drag.
   */
  touch-action: none;
}
/* Half in and half out of the figure's own edge, which is the edge the request
 * named: the sides of the box, not the sides of the picture inside it. Under
 * an answer they are a hundred and forty pixels clear of the coastline, since
 * the drawing is 366 across in a 654 box, and on /size the two are the same
 * edge and the strip is over the empty margin the projection leaves anyway.
 */
.size__edge--w { left: -6px; }
.size__edge--e { right: -6px; }
.size__edge::before {
  content: "";
  position: absolute;
  top: 25%;
  bottom: 25%;
  left: 5px;
  width: 2px;
  border-radius: 1px;
  background: var(--faint);
}
/* ...and the cursor stays the pull's for as long as the pull lasts. The strip
 * captures the pointer, so a hand that runs off it is still pulling, and a
 * cursor that changed back halfway would say otherwise.
 */
.size--pulling { cursor: ew-resize; }
/* Both at the same weight, so the later one is the one that wins. Written as
 * ".size__edge:hover" the second rule lost to the first every time: one class
 * and a pseudo-class does not outrank two classes and a pseudo-class, so
 * landing on an edge left it at the faint opacity the approach had given it
 * and nothing said which of the two the pointer was actually on.
 */
.size__stage:hover .size__edge { opacity: 0.45; }
.size__stage .size__edge:hover,
.size--pulling .size__stage .size__edge { opacity: 1; }
/* No hover to reveal it with, and no room to grow into: a phone's column is
 * the window, so the widest the frame can be is the width it already is. The
 * brackets still work for a keyboard, and the clamp in src/size.js is what
 * makes them honest there.
 */
@media (hover: none), (pointer: coarse) {
  .size__edge { display: none; }
}

/* ===== THE BAR =====
 *
 * Two rows on /size and one under an answer, and the difference is two
 * display:none rules rather than two sets of markup. Row one is the pair, row
 * two is the buttons, the zoom and the count. The count is pushed to the far
 * end with margin rather than placed there, so the group on the left keeps its
 * own width and a button that is hidden simply closes the row up.
 */
.size__bar {
  display: grid;
  gap: 0.4rem;
  margin-top: 0.4rem;
  font-size: 0.85rem;
  color: var(--muted);
}
.size__row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.size__count { margin-left: auto; text-align: right; }
/* The two buttons a reader gets in both forms of the figure: turn it round,
 * and put it back. One shape between them rather than two that would drift.
 */
/* Padded to 24 CSS pixels of height and no less. The bar is at 0.85rem, so the
 * line inside these is 16.3px and the old 0.15rem gave a button 23.1px tall,
 * which is under the floor a pointer target is owed and under what the figure
 * itself argues for the shape a finger has to find.
 */
.size__flip, .size__home, .size__tile {
  font: inherit;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0.3rem 0.6rem;
  cursor: pointer;
}
.size__flip:hover, .size__home:hover, .size__tile:hover {
  border-color: var(--faint);
}
/* Pressed, and it says so twice: aria-pressed for a reader who is told, and
   the fill for a reader who can see it. The word on the button is what the
   press will do next rather than what it did, so a figure showing one shape
   offers "tile" and a figure showing fifteen offers "one". */
.size__tile[aria-pressed="true"] {
  color: var(--bg); background: var(--text); border-color: var(--text);
}
.size__flip:focus-visible, .size__home:focus-visible,
.size__tile:focus-visible {
  outline: 2px solid var(--text);
  outline-offset: 1px;
}

/* The compact form under an answer: the same figure, smaller, because an
 * answer is a place to glance at a picture rather than to study one.
 *
 * Said as a width where it used to be a height cap of 240px, and it is the
 * same drawing to the pixel: 240 tall at 640 by 420 is 365.7 across. The width
 * is the form the reader can now pull, so the compact figure starts exactly
 * where it always started and grows from there, and the same custom property
 * carries the default and the reader's answer to it.
 *
 * What changes and is worth having: the cap letterboxed a 366-pixel drawing
 * inside a 654-pixel svg, so 288 pixels of it were empty border carrying the
 * figure's touch-action and doing nothing at all. The svg is now the drawing.
 */
.size--inline { --size-w: 365.7px; }
/* ...and under an answer the page keeps the swipe until the reader has asked
 * to stand closer, which is the same bargain /size strikes and the whole of
 * what made the zoom safe to give this figure. The shape keeps its drag, the
 * page keeps the rest, and the rule below takes the gesture once there is a
 * frame worth moving.
 */
.size--inline .size__svg { touch-action: pan-y; }
/* Last of the three, and it has to be. The compact rule above and this one are
 * the same specificity, so while this stood higher up the sheet a compact
 * figure that had been zoomed still refused its own frame the pan, because the
 * rule that said pan-y was simply later.
 */
.size--zoomed .size__svg { touch-action: none; }

/* ===== THE FRAME'S OWN ROW =====
 *
 * The pair of steps and the number between them, which only /size draws. The
 * folding rule is here as well as in the markup, on the rule sun.css and
 * clocks.css both keep: the stylesheet says what the compact figure is, and a
 * class that reached it by another route still would not be drawn.
 */
.size__view { display: inline-flex; align-items: center; gap: 0.15rem; }
.size__step {
  font: inherit;
  color: var(--muted);
  background: none;
  border: 1px solid var(--line);
  border-radius: 6px;
  /* A 16px icon at line-height 1 inside 0.1rem of padding is a 21.2 by 29.2
   * button, and the 2.4px between the pair means the spacing exception does not
   * rescue it either. This is 29.2 by 34.
   */
  padding: 0.35rem 0.5rem;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
}
.size__step:hover { color: var(--text); border-color: var(--faint); }
.size__step:focus-visible { outline: 2px solid var(--text); outline-offset: 1px; }
.size__step[disabled] { opacity: 0.45; cursor: default; }
/* A fixed column, or the row reflows every time the number gains a digit. */
.size__zoom {
  min-width: 7.5em;
  text-align: center;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}
/* ...but not while there is no number in it. The column is reserved so that
 * "1.3 times closer" and "16 times closer" do not push the count about between
 * two presses; a figure at fit has nothing to say and would otherwise hold
 * seven and a half ems of nothing in the middle of every ratio answer's bar.
 * The row settles once, on the first press, and never moves again.
 */
.size__zoom:empty { min-width: 0; }

/* ===== THE TWO NAMES =====
 *
 * No breakpoint of its own. flex: 1 1 9rem with wrapping puts the two boxes
 * side by side while the bar is wider than about 19rem and stacks them with
 * the word between them below that, which on a 375px phone is where they land.
 */
.size__pair {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.size__pick {
  font: inherit;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0.15rem 0.4rem;
  cursor: pointer;
  flex: 1 1 9rem;
  min-width: 6rem;
  max-width: 16rem;
}
.size__pick:focus-visible { outline: 2px solid var(--text); outline-offset: 1px; }
.size__word { flex: none; color: var(--muted); }
.size--inline .size__pair { display: none; }

/* ===== THE REST OF THE CANVAS =====
 *
 * The third box and the chips it makes. Both live inside .size__pair, so the
 * one rule above that folds the pair away under an answer folds these away
 * too: there is no second gate to keep in step, and the compact figure cannot
 * grow a third shape by any route.
 *
 * The add box is narrower than the pair and does not grow with them. It is an
 * action rather than a state -- it empties itself the moment it has taken a
 * name -- so it should not be sitting there as wide as the two boxes that are
 * showing what the picture is.
 */
.size__pick--add { flex: 0 1 8rem; color: var(--muted); }
.size__pick--add:disabled { opacity: 0.45; cursor: default; }

/* The whole row of them, on a line of its own under the three boxes. flex-
 * basis 100% rather than a second container, so the chips wrap among
 * themselves and the pair above keeps the layout it already had.
 */
.size__more {
  display: flex;
  flex: 1 1 100%;
  flex-wrap: wrap;
  gap: 0.3rem;
}
/* display:flex outranks the hidden attribute, which is the one thing that has
 * to be said again whenever a flex container is hidden this way.
 */
.size__more[hidden] { display: none; }

/* One shape's name, and the way it comes off. The cross is drawn by the sheet
 * rather than written into the markup, so the button's text is exactly the
 * name a reader has to match against the drawing and nothing else is read out
 * beside it.
 *
 * Padded to the same 24 CSS pixels the other controls in this figure are held
 * to: 0.85rem of bar is a 16.3px line, and 0.3rem either side of it is 25.9.
 */
.size__chip {
  font: inherit;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0.3rem 0.5rem;
  cursor: pointer;
}
.size__chip::after {
  content: " \00d7";
  color: var(--muted);
}
.size__chip:hover { border-color: var(--faint); }
.size__chip:hover::after { color: var(--text); }
.size__chip:focus-visible { outline: 2px solid var(--text); outline-offset: 1px; }

@media (max-width: 560px) {
  .size__bar { font-size: 0.8rem; }
  /* The count is a sentence rather than a chip, and squeezed into the tail of
   * a row of buttons it wraps to two words a line.
   */
  .size__count { margin-left: 0; flex: 1 1 100%; text-align: left; }
  .size__zoom { min-width: 6.5em; }
}

@media (prefers-reduced-motion: reduce) {
  .size__of { transition: none; }
  .size--dragging .size__of { filter: none; }
  /* The edges appear rather than fade. The figure holds still for anybody who
   * asked it to, and a control that is only there to be grabbed is the last
   * thing that should be arriving over an eighth of a second.
   */
  .size__edge { transition: none; }
}
