/*
 * GENERATED FILE — DO NOT EDIT.
 *
 * Source:    sites/shared/components/latchbox/latchbox.css
 * Regenerate: python3 scripts/sync-shared.py   (from sites/)
 *
 * This copy exists only because HQ embeds its frontend with go:embed, which
 * cannot reference files outside its module. Edit the source; changes made
 * here are overwritten and will fail `sync-shared.py --check`.
 */

/* ============================================================================
 * latchbox — a well of keys, one of them always down
 * ============================================================================
 *
 * A rectangle with keys sitting in it. Every key is raised at rest; the chosen
 * one is pressed flat against the floor of the well and STAYS there. Choosing
 * another releases the first. The position IS the state — there is no separate
 * indicator to keep in agreement with it.
 *
 * ---- Using it --------------------------------------------------------------
 *
 *   <link rel="stylesheet" href="/shared/components/latchbox/latchbox.css">
 *   <script src="/shared/components/latchbox/latchbox.js" defer></script>
 *
 *   <div class="latchbox" role="radiogroup" aria-label="Theme">
 *     <button class="latchbox-key" role="radio" aria-checked="true"  value="light">Light</button>
 *     <button class="latchbox-key" role="radio" aria-checked="false" value="dark">Dark</button>
 *   </div>
 *
 * EXACTLY ONE KEY IS DOWN, ALWAYS, and that is what separates this from the
 * marketing site's `.prim-latch`. That control can be released to nothing —
 * pressing the key already down empties its readout — so each of its keys is an
 * independent toggle and `aria-pressed` describes it correctly. This one models
 * a choice with no "neither" position, so it is a radiogroup: pressing the key
 * already down does nothing, and arrow keys move the selection. Same gesture,
 * different semantics, and the ARIA has to say which.
 *
 * ---- The geometry, which is the whole component ----------------------------
 *
 * A raised key sits --latchbox-lift ABOVE the floor with a hard shadow filling
 * the gap underneath it; a pressed key sits ON the floor with no shadow. So the
 * well needs exactly that much room above the key's layout box and none below
 * it — hence `padding-top: var(--latchbox-lift)` and `padding-bottom: 0`.
 *
 * Both are derived from the one token rather than written as numbers, because
 * they are the same fact twice and a well that disagrees with its keys either
 * clips the raised one or leaves the pressed one floating. A transform does not
 * change layout, so the box the well sizes to is the same in both positions and
 * nothing reflows when a key moves.
 *
 * ---- Layer -----------------------------------------------------------------
 *
 * `component`, as every shared component is — the order is declared once in
 * brand.css (brand, site, component, page), so this outranks a site's own layout
 * and is outranked by the page hosting it, wherever the <link> sits.
 * ========================================================================== */
@layer component {

.latchbox {
  /* The travel. The brand's toy-affordance table gives 3px to dense chrome
     controls and 4px to cards; a switch in a topbar is chrome, so it takes the
     smaller gesture. */
  --latchbox-lift: 3px;
  /* The air between a key and the well it sits in — sides, and underneath. */
  --latchbox-inset: 4px;

  display: inline-flex;
  /* Stretch, so a key takes its height FROM the well. When a host stands the
     well to a fixed height the keys fill what is left after the padding, which
     is the only version that cannot overflow: sized from their own padding
     instead, they overran a 40px shelf by 4.3px and the raised key's top edge
     crossed the border. Measured, not guessed. With no height given, the well
     still sizes to the keys and nothing changes. */
  align-items: stretch;
  gap: var(--latchbox-inset);
  box-sizing: border-box;
  /* THE RAISED STATE IS THE RESTING STATE, so that is the one that gets to look
     evenly inset: the top carries the inset PLUS the lift, so a key at rest has
     the same air above it as below and pressing reads as descending into the
     well rather than as the row shifting.
     A pressed key clears the floor by the inset rather than landing on it. Flush
     to the bottom edge made the well read as a slot the keys were cut out of;
     with a floor gap it reads as a housing they sit in, which is what it is.
     Both numbers are derived from the two tokens, so a change to either cannot
     leave the well disagreeing with its keys. */
  padding: calc(var(--latchbox-inset) + var(--latchbox-lift))
           var(--latchbox-inset)
           var(--latchbox-inset);
  /* The desk, showing through the panel the bar is made of. That contrast is
     what makes this read as a recess rather than as another raised plate —
     there is no inset shadow to reach for, because a blurred shadow is not a
     thing this brand has. */
  background: var(--bg);
  border: 2px solid var(--ink);
  border-radius: 0;
  /* A host that stands its occupants to a height says so with this. The fallback
     is a NUMBER rather than `auto`, and that is not tidiness: the keys are
     square, so with an auto height the well's height depends on the key's width
     which depends on the key's height. A flex row resolves that circle at
     whatever space it happens to have, and in a navbar it resolved to 304px
     keys. A component that explodes when an OPTIONAL token is absent is a
     component that only works where it was first used. */
  height: var(--latchbox-h, 36px);
}

.latchbox-key {
  /* Its own box centres the label, so the vertical padding below only decides
     the key's height when the well is free to size itself. Under a stated
     height the padding is slack and the label stays centred anyway. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Square, from whatever height the well ends up with. A key that carries a
     drawn object rather than a word has no text to take a width from, and a
     square is the shape a physical key is anyway. */
  aspect-ratio: 1;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1;
  color: var(--ink);
  background: var(--panel);
  border: 2px solid var(--toy-edge);
  border-radius: 0;
  padding: 0;
  cursor: pointer;
  /* Raised at rest — already up, waiting to be pushed. The shadow is ink,
     hard-edged and directly below; #000 is a bug and a blur is a bug. */
  transform: translateY(calc(-1 * var(--latchbox-lift)));
  box-shadow: 0 var(--latchbox-lift) 0 var(--toy-edge);
  transition: transform .08s cubic-bezier(.34, 1.56, .64, 1),
              box-shadow .08s cubic-bezier(.34, 1.56, .64, 1),
              background-color .12s ease, color .12s ease;
}

/* NO HOVER RAISE, and this is a rule rather than an omission. Raised-at-rest has
   two positions, up and pressed, and this starts in the first. If height means
   selected, height must not also mean "the pointer is here". */

/* Pressed, while the pointer is down — the same place the chosen key lives, so
   choosing looks like the key simply staying where you put it. Declared BEFORE
   the checked rule so source order keeps the chosen key down when the pointer
   leaves it. */
.latchbox-key:active {
  transform: translateY(0);
  box-shadow: 0 0 0 transparent;
}

/* Chosen. Down, and inverted.
   Two signals for one fact, deliberately. Position alone carries it on the
   marketing site's picker, but that control is a 4px gesture on keys the size of
   a thumb; this one is 3px in a topbar, where the travel is honest but small.
   Ink fill is the same "this one is chosen" the hero stat cards already use, so
   the second signal is borrowed rather than invented. */
.latchbox-key[aria-checked="true"],
.latchbox-key[aria-pressed="true"] {
  transform: translateY(0);
  box-shadow: 0 0 0 transparent;
  background: var(--ink);
  /* --panel, NOT #fff. The fill is --ink, so the label has to be whatever --ink
     is not, and only a token tracks that. Written as #fff this is invisible the
     moment the palette is re-grounded — measured, not predicted: under the dark
     proof it rendered white on #e8ecf3. The same trap sidenav.css names for its
     own active row. */
  color: var(--panel);
}

/* ---- A well that spans its container, with labelled keys -------------------
 * The default well is inline and its keys are square, because the first one
 * carries a glyph. A row of keys carrying WORDS is the other shape: it fills the
 * width it is given and the keys divide it.
 *
 * A variant rather than a new component — the mechanism is identical, and the
 * only things that differ are how wide the well is and what a key is shaped by.
 * The label sets the height here, so a host states no --latchbox-h. */
.latchbox--wide {
  display: flex;
  width: 100%;
  /* The label decides the height unless a host says otherwise. Written through
     the token rather than as a flat `auto`, which would out-rank the base rule
     (same specificity, later in the file) and make --latchbox-h inert here. */
  height: var(--latchbox-h, auto);
}
.latchbox--wide .latchbox-key {
  /* Equal shares. min-width:0 because a flex item refuses to shrink below its
     content by default, and one long label would otherwise push the row wider
     than the well. */
  flex: 1;
  min-width: 0;
  aspect-ratio: auto;
  padding: 0.85rem 1rem;
  font-size: 1.05rem;
  text-align: center;
}

/* The glyph takes its colour from the key, which is what lets one file sit on a
   raised key and on the inverted chosen one without knowing either. Sized as a
   share of the key rather than in pixels, so it follows whatever height the host
   gave the well. */
.latchbox-key svg {
  display: block;
  width: 62%;
  height: 62%;
  fill: currentColor;
}

.latchbox-key:focus-visible {
  outline: 2px solid var(--brand-2);
  outline-offset: 2px;
}

/* An accessible name for a control whose only visible content is a drawing.
   Positioned out of sight rather than hidden, because display:none and
   visibility:hidden would take it from a screen reader too.

   brand.css carries a `.sr-only` of its own and this one stays anyway — the
   duplication is chosen. A component must not inherit anything that can differ
   between hosts, and borrowing this would lose every accessible name on a
   surface that has not loaded brand.css. Scoped, so the two never collide. */
.latchbox .sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* The travel is the whole component, so with motion off the state still has to
   be readable — the fill and the resting position do it without animating. */
@media (prefers-reduced-motion: reduce) {
  .latchbox-key { transition: none; }
}

} /* @layer component */
