/* ============================================================
   The site navigation bar, shared by every page of the site, the explainer included.
   Part of the design system in paper-design.md. Written in kpress tokens only. Hidden in print, so the explainer's PDF and its
   print-layout checks do not move.
   ============================================================ */
/* The gentle wash of a hovered card or nav item, a table's group row and a targeted row,
   here because every page carries this file. KPress's own dark hover surface is a light
   gray that light text cannot sit on, so dark mode washes with a tint of the text. The
   shadow under a floating panel, the theme menu and a popover, and the tint of the
   current tab are here for the same reason. Every colour is a token
   (`devtools.check_colour_tokens`, paper-design.md, Color). */
:root {
  --site-wash: var(--kpress-doc-surface-hover);
  --site-shadow: oklch(0% 0 0 / 0.15);
  --site-tab-current-tint: 16%;
}
/* ---------- Motion ----------
   Every hover and focus change on the site runs on one timing, fast and smooth, here
   because every page carries this file (paper-design.md, Motion). A change of colour,
   a wash, a text colour, a border or a shadow, eases on one value,
   `--site-hover-transition`, which every element whose hover or focus changes one
   carries at rest, so the change eases in and out; it names those four properties and
   never `all`, so a late stylesheet snaps into place rather than animating its layout.
   What else a hover moves, an arrow's nudge or an icon's fade, transitions that one
   property on the same timing, never with a literal time. KPress's own hover timing
   takes the same value, so its contents rail and footnote links match. Reduced motion
   makes every change instant. */
:root {
  --site-hover-duration: 140ms;
  --site-hover-easing: ease-out;
  --site-hover-transition:
    background-color var(--site-hover-duration) var(--site-hover-easing),
    color var(--site-hover-duration) var(--site-hover-easing),
    border-color var(--site-hover-duration) var(--site-hover-easing),
    box-shadow var(--site-hover-duration) var(--site-hover-easing);
}
@media (prefers-reduced-motion: reduce) {
  :root {
    --site-hover-duration: 0ms;
    --site-hover-transition: none;
  }
}
/* At every scope KPress declares its token, so this value is the one each finds. */
:root,
.kpress,
.kpress-page-main,
.kpress-tooltip {
  --kpress-transition-fast: var(--site-hover-duration) var(--site-hover-easing);
}
/* The space above the bar, on every page and at every width: kpress's page top margin,
   narrowed from its 2.5rem so the bar sits close to the top of the window. It sets only
   the padding above the header (kpress's page main, and the application shell below). */
:root,
.kpress,
.kpress-page-main {
  --kpress-page-margin-block-start: 1rem;
  --site-page-top: 4rem;
  --site-gear-drop: 0.11em;
}
/* The space from the bar's rule to the top of a page's first block (its title, its hero,
   or the explainer's hero), one token for every page: kpress's document padding above
   the column is dropped on screen, and the column (site.css) or the explainer's hero
   (paper-publication.css) starts `--site-page-top` below the rule instead. Print keeps
   kpress's own spacing, so the explainer's PDF does not move. */
@media screen {
  .kpress-page-main > .kpress-doc {
    padding-block-start: 0;
  }
}
:root:where([data-kpress-resolved-theme="dark"]),
:where([data-kpress-resolved-theme="dark"]) :is(.kpress, .kpress-page-main, .kpress-tooltip),
:is(.kpress, .kpress-page-main, .kpress-tooltip)[data-kpress-resolved-theme="dark"] {
  --site-wash: color-mix(in oklch, var(--kpress-doc-text) 9%, transparent);
}
/* The site's accent in dark mode, here rather than in site.css because every page carries
   this file, the workbench included, and the bar's current item is drawn in it. kpress
   declares the light value. */
:root:where([data-kpress-resolved-theme="dark"]),
:where([data-kpress-resolved-theme="dark"]) :is(.kpress, .kpress-page-main, .kpress-tooltip),
:is(.kpress, .kpress-page-main, .kpress-tooltip)[data-kpress-resolved-theme="dark"] {
  --kpress-doc-accent: oklch(76.68% 0.0861 186.4);
}
/* ---------- Navigation bar ----------
   Carried in kpress's own site-header slot, which spans the window, with its links in
   one fixed-width track so the bar sits in the same place on every page: the pages set
   different reading measures, and a track sized from the measure moved it. */
.kpress-site-header,
.kpress-page-main:has(.kpress-toc) .kpress-site-header {
  max-width: none;
  padding: 0;
}
/* The bar's type, on the paper's scale (paper-type.css, which the site's pages, the
   explainer and the workbench inline). The body is 18px prose. The bar's links, and a section's tabs, are one
   step below the body and no more: the note size, 0.92 of the sans base, 17.48px, which
   is the first size on the scale under 18px (the support size between them, 0.95, is
   18.05px). The site's name is the sans base, 19px, the size sans text takes beside the
   prose, and heavier, so it reads as the name. Both are taken from the host base, which
   is the same on every page, not from KPress's derived base, which a page may rescale,
   so the bar does not change size between pages. The optimality paper carries the bar
   without paper-type.css, so each token names the paper's own value as its fallback
   there; a test holds the three fallbacks to paper-type.css. */
:root {
  --site-nav-name-size: calc(
    var(--kpress-host-font-size-base, 18px) *
    var(--paper-font-scale-sans, calc(19 / 18))
  );
  --site-nav-font-size: calc(var(--site-nav-name-size) * var(--paper-note-scale, 0.92));
  /* The line every item of the bar is set on: the links' own, 1.43 of their size, which
     is the face's leading there (25px). A length and not a ratio, so the name, a size
     larger, takes the links' line and not a taller one of its own. */
  --site-nav-line: calc(var(--site-nav-font-size) * 1.43);
}
.site-nav {
  font-family: var(--kpress-font-sans);
  font-feature-settings: var(--kpress-font-features-sans);
  font-size: var(--site-nav-font-size);
}
.site-nav-inner {
  align-items: baseline;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.4rem;
  margin-inline: auto;
  max-width: 70rem;
  padding: 0.55rem 1rem;
}
/* Every item, the site name included, is a padded box that takes a gentle wash on
   hover, the cards' own hover; nothing underlines on hover. */
.site-nav a {
  color: var(--kpress-doc-muted);
  font-weight: 550;
  line-height: var(--site-nav-line);
  padding: 0.25rem 0.55rem;
  text-decoration: none;
  transition: var(--site-hover-transition);
}
.site-nav a:is(:hover, :focus-visible) {
  background: var(--site-wash);
  color: var(--kpress-doc-accent);
  text-decoration: none;
}
/* The name is set as written, in the bar's sans, a step heavier than the links. */
/* The site name is set in capitals by style, so its text stays "Square Packing". */
.site-nav .site-name {
  color: var(--kpress-doc-text);
  font-size: var(--site-nav-name-size);
  font-weight: 680;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-inline: -0.55rem auto;
}
/* The mark, case 11 as the tab's icon draws it, sits before the name, centred on the
   name's line, in the bar's ink, and takes the name's hover with it. */
.site-nav .site-name {
  align-items: center;
  display: inline-flex;
  gap: 0.45rem;
}
/* The name's text stands on the links' baseline. The bar aligns its items by their
   baselines, and the name is a row of its own, a mark and the text, whose baseline would
   be its first item's, the mark's lower edge: the links' text then stood level with the
   foot of the mark, and the name's text, centred on the mark, some pixels above it. The
   text is the one item of that row aligned by its baseline, so the row's baseline is the
   text's, at any size of either, and the mark stays centred on the text's line. That
   line is the links' own (`--site-nav-line`), so the name is no taller than a link and
   the links stand where they do without it, the current one's underline the same
   distance over the rule at every width. */
.site-nav .site-name-text {
  align-self: baseline;
}
/* 18px, whole pixels, the size `render_overview.SITE_LOGO_PX` draws its one-pixel frame
   for, so the container's outline is one crisp pixel (two on a 2x screen). */
.site-nav .site-logo {
  block-size: 18px;
  flex: none;
  inline-size: 18px;
}
.site-nav .site-name:is(:hover, :focus-visible) {
  color: var(--kpress-doc-text);
}
/* The current page is the one underline in the bar, and it stays through a hover. */
.site-nav a[aria-current="page"] {
  color: var(--kpress-doc-accent);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.35em;
}

/* ---------- Theme control ----------
   A small gray gear at the end of the bar opens a compact menu of three choices, System,
   Light and Dark, the current one checked. The choice is kpress's own reader preference
   (`kpress.theme`), which kpress's head bootstrap applies before first paint, so the
   stylesheets only ever key on `data-kpress-resolved-theme`; overview/theme.js wires the
   menu. The gear takes the nav items' wash and never underlines. */
/* The bar centres the gear on its row, but the eye reads a row of text at the middle of
   its capitals, which sits lower than the middle of its line box, so the gear drops by
   `--site-gear-drop` to put its centre there, level with the tab text at every width. */
.site-theme {
  align-self: center;
  display: flex;
  flex: 0 0 auto;
  translate: 0 var(--site-gear-drop);
}
/* On a wide screen the links keep their centred track and the gear leaves it for the
   bar's far right, its edge over the right end of the rule under the bar. From 80rem
   the margin beside the 70rem track holds it clear of the last link; below that the
   track spans the bar, and the gear ends the row. */
@media (width >= 80rem) {
  .site-nav {
    position: relative;
  }
  .site-nav .site-theme {
    inset-block: 0;
    inset-inline-end: 0;
    position: absolute;
  }
}
.site-theme-button {
  align-items: center;
  background: none;
  border: 0;
  color: var(--kpress-doc-muted);
  cursor: pointer;
  display: flex;
  font: inherit;
  padding: 0.3rem 0.45rem;
  transition: var(--site-hover-transition);
}
.site-theme-button svg {
  block-size: 1.05rem;
  inline-size: 1.05rem;
}
.site-theme-button:is(:hover, :focus-visible, [aria-expanded="true"]) {
  background: var(--site-wash);
  color: var(--kpress-doc-text);
}
/* The menu is a native popover, so it sits in the top layer above the bar's sideways
   scroll on a phone and closes on Escape or an outside click by itself; the script
   places it under the gear. The place below is only where it opens without the script. */
.site-theme-menu {
  background: var(--kpress-doc-bg);
  border: 1px solid var(--kpress-doc-border);
  box-shadow: 0 0.5rem 2rem var(--site-shadow);
  color: var(--kpress-doc-text);
  font-family: var(--kpress-font-sans);
  font-feature-settings: var(--kpress-font-features-sans);
  font-size: 0.9rem;
  inset: 3rem 1rem auto auto;
  margin: 0;
  min-inline-size: 8.5rem;
  padding: 0.25rem;
  position: fixed;
}
.site-theme-menu:popover-open {
  display: flex;
  flex-direction: column;
}
.site-theme-menu [role="menuitemradio"] {
  align-items: center;
  background: none;
  border: 0;
  color: var(--kpress-doc-muted);
  cursor: pointer;
  display: flex;
  font: inherit;
  font-weight: 550;
  gap: 0.55rem;
  padding: 0.35rem 0.55rem;
  text-align: start;
  transition: var(--site-hover-transition);
}
.site-theme-menu [role="menuitemradio"]:is(:hover, :focus-visible) {
  background: var(--site-wash);
  color: var(--kpress-doc-text);
  outline: none;
}
.site-theme-menu [role="menuitemradio"][aria-checked="true"] {
  color: var(--kpress-doc-accent);
}
.site-theme-menu svg {
  block-size: 1em;
  flex: 0 0 auto;
  inline-size: 1em;
}
.site-theme-menu .site-theme-check {
  margin-inline-start: auto;
  visibility: hidden;
}
.site-theme-menu [aria-checked="true"] .site-theme-check {
  visibility: visible;
}

@media print {
  .site-nav,
  .kpress-site-header {
    display: none;
  }
}
/* On a phone the links keep to one row that scrolls sideways rather than wrapping to
   three lines; the site name goes, since "Overview" is the same link. */
/* On a phone every link stays in view: the row wraps, centred, rather than scrolling
   links out of sight, and the gear ends the last line. */
/* On a phone the links wrap to two or three rows, so each row is set closer: a shorter
   line and less padding above and below each link, with no gap between rows. A link
   stays 26px tall, above the 24px a tap target needs. */
@media (width < 40rem) {
  .site-nav-inner {
    gap: 0 0.1rem;
    justify-content: center;
    padding-block: 0.4rem;
    padding-inline: 0.5rem;
  }
  .site-nav a {
    line-height: 1.3;
    padding-block: 0.15rem;
    padding-inline: 0.45rem;
  }
}
/* Narrower than the whole bar fits in one row with the name (56rem), the name gives
   way and the mark alone leads home, so the links keep one row down to a phone. The
   link keeps its label, "Square Packing home", for a screen reader. */
@media (width < 56rem) {
  .site-nav .site-name-text {
    display: none;
  }
  .site-nav .site-name {
    align-self: flex-start;
  }
}
/* On the explainer the bar is the first thing in the page, not in kpress's header slot. */
.kpress-page-main > .site-nav {
  border-block-end: 1px solid var(--kpress-doc-border);
}

/* ---------- Closing credit ----------
   The footer's two lines, here because every page that has a footer carries this file:
   the site's pages set them in `.site-colophon` (site.css) and the papers in their own
   `.colophon` (`render_overview.colophon_lines` writes the lines for all of them). A
   line is a block, so there are two at every width. A part, what stands on one side of
   a middle dot, is an inline block: a line too long for a phone breaks at the dot, and
   only a part wider than the page breaks inside itself, into balanced rows rather than
   one word alone on the last. */
.site-colophon-line {
  display: block;
}
.site-colophon-part {
  display: inline-block;
  text-wrap: balance;
}

/* ---------- On an application page ----------
   The workbench is an application rather than a kpress page, so nothing around the bar
   gives it the margins kpress's standalone page gives every other page, nor the rule under
   its header slot. Its shell (`render_overview.nav_shell`) takes both itself, from the same
   tokens, so the bar has the same box on every page at every width. The shell is the
   page's width and paints the page's background, so the application below starts at its
   lower edge. A shell that carries section tabs has its rule under the bar, above them
   (Section tabs, below). */
.site-app-shell {
  background: var(--kpress-doc-bg);
  box-sizing: border-box;
  color: var(--kpress-doc-text);
  flex: none;
  padding: var(--kpress-page-margin-block-start) var(--kpress-page-margin-inline) 0;
  width: 100%;
}
.site-app-shell .kpress-site-header {
  border-block-end: 1px solid var(--kpress-doc-border);
  box-sizing: border-box;
  margin: 0;
  width: 100%;
}
/* kpress narrows its page margin on a phone; so does the shell. */
@media (max-width: 767px) {
  .site-app-shell {
    --kpress-page-margin-inline: 0.5rem;
  }
}

/* ---------- Section tabs ----------
   A section of the site that spans pages, the Visualize section's Film and Workbench,
   carries one small tab bar in the header slot under the navigation bar, in the same
   place on each of its pages: a centred, bordered strip of links, one per page, the
   current one filled with an accent tint. Each tab is a real link to its own page, so
   the bar needs no script. It is here rather than in site.css because the workbench
   carries only this stylesheet, and the tabs must look the same on both pages. The tint
   is mixed in sRGB, since an oklch mix with the near-neutral page takes that page's
   hue and drew the light tab lavender rather than teal.
   The same strip also switches a view in place: there it is a tablist of buttons
   (`role="tab"`), the selected one filled as the current page's link is. The homepage's
   atlas uses it for its Grid and Triangle views (site.css places it). */
/* The tabs sit below the rule under the bar, not above it. That rule is the header
   slot's lower border and the tabs are in the slot, so a header that holds tabs hands
   its rule to the bar: from the top, the bar, the rule, then the tabs. The bar spans
   the header, so the rule is where it is on every other page, and as long. */
.kpress-site-header:has(> .site-tabs) {
  border-block-end: 0;
}
.kpress-site-header > .site-nav:has(+ .site-tabs) {
  border-block-end: 1px solid var(--kpress-doc-border);
}
/* The tabs stand `--site-tabs-space` under the rule. On a kpress page nothing follows
   them in the header, so the page's first block starts `--site-page-top` under the
   tabs; an application starts at its shell's lower edge, so there the tabs keep the
   same space below as above. */
.site-tabs {
  --site-tabs-space: 0.7rem;
  border: 1px solid var(--kpress-doc-border);
  display: flex;
  font-family: var(--kpress-font-sans);
  font-feature-settings: var(--kpress-font-features-sans);
  font-size: var(--site-nav-font-size);
  inline-size: fit-content;
  margin: var(--site-tabs-space) auto 0;
}
.site-app-shell .site-tabs {
  margin-block-end: var(--site-tabs-space);
}
/* A button tab takes the strip's type and none of a button's own chrome. */
.site-tabs [role="tab"] {
  background: none;
  border: 0;
  border-radius: 0;
  cursor: pointer;
  font: inherit;
}
nav.site-tabs a,
.site-tabs [role="tab"] {
  color: var(--kpress-doc-muted);
  font-weight: 550;
  padding: 0.3rem 1.1rem;
  text-decoration: none;
  transition: var(--site-hover-transition);
}
nav.site-tabs a + a,
.site-tabs [role="tab"] + [role="tab"] {
  border-inline-start: 1px solid var(--kpress-doc-border);
}
nav.site-tabs a:is(:hover, :focus-visible),
.site-tabs [role="tab"]:is(:hover, :focus-visible) {
  background: var(--site-wash);
  color: var(--kpress-doc-accent);
  text-decoration: none;
}
nav.site-tabs a[aria-current="page"],
.site-tabs [role="tab"][aria-selected="true"] {
  background: color-mix(
    in srgb,
    var(--kpress-doc-accent) var(--site-tab-current-tint),
    var(--kpress-doc-bg)
  );
  color: var(--kpress-doc-text);
}
@media print {
  .site-tabs {
    display: none;
  }
}

/* A page framed in a card's popover (`?view=embed`, set by overview/embed.js) shows the
   document alone: no navigation bar, and no section tabs. */
:root[data-site-view="embed"] .site-tabs,
:root[data-site-view="embed"] .kpress-site-header,
:root[data-site-view="embed"] .site-nav {
  display: none;
}
/* Nor the room left for it: the document starts at the frame's top edge. */
:root[data-site-view="embed"] .kpress-page-main {
  padding-block-start: 0;
}
:root[data-site-view="embed"] .kpress-page-main > .kpress-doc {
  padding-block-start: 0.5rem;
}
