/* Milky Way, under the house system (Template/HOUSE.md; ART.md is this app's direction).

   The plate is space in both themes: it has one true appearance. The chrome around it follows the
   phone's theme: film base and ink by day, the slate print by night. One face, no accent color, no
   glass, no shadows, no gradient in the chrome but the selection tracer. The one bold thing is the
   Reach in the caption band (js/rule.js). Nothing here is fetched. */

@font-face {
  font-family: 'Ysabeau Office';
  src: url(fonts/ysabeau-office-gw.woff2) format('woff2');
  font-weight: 400 650;
  font-display: block;
}
/* the Greek letters, the superscript figures and the okina the data's names use (ART.md section 4) */
@font-face {
  font-family: 'Ysabeau Office';
  src: url(fonts/ysabeau-office-milky-way-extra.woff2) format('woff2');
  font-weight: 400 650;
  font-display: block;
  unicode-range: U+02BB, U+03B1-03C9, U+2074-2079;
}

:root {
  --page: #e8eef0;            /* header, caption band, player */
  --sheet: #f6f9fa;           /* key plates, the card, the sheets, notices */
  --ink: #0f1c23;
  --ink-2: #45555d;
  --ink-3: #5b6a72;
  --line: #c9d4d8;
  --line-strong: #74858c;
  --draw: cubic-bezier(0.2, 0, 0, 1);
  --sheet-in: cubic-bezier(0.32, 0.72, 0, 1);
  --face: 'Ysabeau Office', system-ui, -apple-system, sans-serif;
  --reach: #0d131c;           /* the signature: the Reach's ink and its notch */
  --plate: #020308;           /* space, the renderer's clear color, in both themes */
  --plate-ink: #e6edee;
  --plate-ink-2: #a3b1b6;
  --plate-halo: rgba(2, 3, 8, 0.85);
  color-scheme: light;
}
@media (prefers-color-scheme: dark) {
  :root {
    --page: #141d21;
    --sheet: #1c272c;
    --ink: #e6edee;
    --ink-2: #a3b1b6;
    --ink-3: #8b9a9f;
    --line: #2a373c;
    --line-strong: #64757b;
    --reach: #eff4fa;
    color-scheme: dark;
  }
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: var(--page);
  color: var(--ink);
  font: 400 13.5px/1.35 var(--face);
  font-variant-numeric: tabular-nums lining-nums;
  -webkit-text-size-adjust: 100%;
  overscroll-behavior: none;
}
body { display: flex; flex-direction: column; height: 100vh; height: 100dvh; }
h1, h2, h3, h4, p { margin: 0; }
button, input { font: inherit; color: inherit; }
button {
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
button[disabled] { opacity: 0.4; cursor: default; }
.keyplate button, .ghost, .card-close, .tkey, .shutter, .layer-row .box { display: flex; align-items: center; justify-content: center; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
svg { display: block; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
svg .fill { fill: currentColor; stroke: none; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; margin: -1px; }

/* ── header: the name, About, the stamp while loading, the scale words ── */

.head {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: 22px auto 44px;
  padding: calc(6px + env(safe-area-inset-top)) calc(16px + env(safe-area-inset-right)) 0 calc(16px + env(safe-area-inset-left));
}
.head h1 { grid-area: 1 / 1; font-size: 15px; font-weight: 650; line-height: 22px; }
.stamp-home { grid-area: 2 / 1 / 3 / 3; min-width: 0; padding-bottom: 6px; }
.hkeys { grid-area: 1 / 2; align-self: center; display: flex; position: relative; z-index: 1; }
/* 44 px of hit: down over the scale row's empty end */
.hkeys .wordkey::before { inset: -6px -1px -14px; }
.stamp { position: relative; display: block; max-width: 100%; text-align: left; font-size: 11.5px; line-height: 16px; color: var(--ink-2); }
.stamp::before { content: ''; position: absolute; inset: -22px 0 -6px 0; }       /* 44 px of hit */
/* in focus mode it heads the caption; its hit stays in the band */
.caption > .wordkey { display: block; margin: 5px 0 4px; }
.caption > .wordkey::before { inset: -9px -1px; }
.scales { grid-area: 3 / 1 / 4 / 3; display: flex; margin: 0 -8px; }
.scales button { position: relative; min-width: 44px; height: 44px; padding: 0 8px; font-size: 12.5px; color: var(--ink-2); white-space: nowrap; }
/* the chosen word: weight 620 and the tracer under it, drawn from its tail to its head */
.scales button[aria-pressed="true"] { color: var(--ink); font-weight: 620; }
.scales button[aria-pressed="true"]::after, .lbl.sel span::after {
  content: '';
  position: absolute;
  left: 6px;
  right: 6px;
  bottom: 9px;
  height: 4px;
  background:
    radial-gradient(circle at calc(100% - 2px) 50%, var(--ink) 1.9px, transparent 2.1px),
    linear-gradient(90deg, transparent, var(--ink) calc(100% - 3px), transparent calc(100% - 3px)) 0 1px / 100% 2px no-repeat;
  animation: tracer-in 160ms var(--draw);
}
@keyframes tracer-in { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }

/* ── the plate: space, the 3D view edge to edge ── */

.plate { position: relative; flex: 1 1 auto; min-height: 0; overflow: hidden; background: var(--plate); user-select: none; -webkit-user-select: none; }
#gl { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }
#labels { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }

/* labels on the plate: the face over a halo of space, a 4 px point mark, no pill */
.lbl {
  position: absolute;
  left: 0;
  top: 0;
  display: flex;
  align-items: center;
  gap: 5px;
  height: 20px;
  padding: 0 6px;
  white-space: nowrap;
  font: 560 11.5px/1 var(--face);
  color: var(--plate-ink);
  paint-order: stroke fill;
  -webkit-text-stroke: 3px var(--plate-halo);
  transform-origin: 0 50%;
  will-change: transform;
}
.lbl i { flex: 0 0 auto; width: 4px; height: 4px; border-radius: 50%; background: var(--c, var(--plate-ink)); outline: 1.5px solid var(--plate-halo); }
.lbl span { position: relative; }
.lbl.minor { font-weight: 400; font-size: 11px; color: var(--plate-ink-2); }
.lbl.faint { font-weight: 400; font-size: 10.5px; color: var(--plate-ink-2); }
.lbl.left { flex-direction: row-reverse; }
.lbl.sel { font-weight: 620; font-size: 11.5px; color: var(--plate-ink); }
.lbl.sel span::after { left: 0; right: -2px; bottom: -5px; animation: none; --ink: var(--plate-ink); }
.lbl.bare i { visibility: hidden; }

/* the key column: plates of --sheet, each key a 44 px hit, the plate 36 px wide */
.keys {
  position: absolute;
  top: 8px;
  right: calc(8px + env(safe-area-inset-right));
  z-index: 3;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.keyplate { width: 38px; border: 1px solid var(--line); border-radius: 6px; background: var(--sheet); }
.keyplate button { position: relative; width: 44px; height: 44px; margin: 0 -4px; color: var(--ink-2); }
.keyplate button + button::after { content: ''; position: absolute; left: 4px; right: 4px; top: 0; height: 1px; background: var(--line); }
.keyplate button svg { position: relative; }
.keyplate button::before { content: ''; position: absolute; inset: 8px; border-radius: 4px; }
.keyplate button[aria-expanded="true"] { color: var(--ink); }
.keyplate button[aria-expanded="true"]::before { background: color-mix(in srgb, var(--ink) 12%, transparent); }
.keyplate button:active::before { background: color-mix(in srgb, currentColor 22%, transparent); }
.tkey:active > svg, .textkey:active { background: color-mix(in srgb, currentColor 12%, transparent); border-radius: 4px; }
/* a plate too short for the column (a phone on its side): the keys run as a row along the top */
.keys-row .keys { flex-direction: row; }
.keys-row .keyplate { display: flex; width: auto; height: 38px; }
.keys-row .keyplate button { margin: -4px 0; }
.keys-row .keyplate button + button::after { left: 0; right: auto; top: 8px; bottom: 8px; width: 1px; height: auto; }

/* the ghost key: no plate, a halo of space under the mark, the same in both themes (the plate is) */
.ghost {
  position: absolute;
  top: calc(8px + env(safe-area-inset-top));
  right: calc(8px + env(safe-area-inset-right));
  z-index: 4;
  width: 44px;
  height: 44px;
  opacity: 0.72;
  animation: fade-in 200ms var(--draw);
}
.ghost:focus-visible, .ghost:active { opacity: 1; }
.ghost .halo { stroke: rgba(2, 3, 8, 0.75); stroke-width: 3.4; }
.ghost .halo circle { fill: rgba(2, 3, 8, 0.75); }
.ghost .mark { stroke: #f2f4f1; stroke-width: 1.4; }
.ghost .mark .fill { fill: #f2f4f1; }
@keyframes fade-in { from { opacity: 0; } }

/* the selected object's card */
.card {
  position: absolute;
  left: calc(8px + env(safe-area-inset-left));
  top: 8px;
  z-index: 3;
  width: min(280px, calc(100% - 76px));
  max-height: max(34%, 144px);     /* ART.md section 3 */
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 2px 4px 6px 12px;
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  background: var(--sheet);
  animation: card-in 120ms var(--draw);
}
@keyframes card-in { from { opacity: 0; transform: translateY(4px); } }
.card.low { top: auto; bottom: 8px; }
.focus .card:not(.low) { top: calc(8px + env(safe-area-inset-top)); }
.card-kind { display: flex; align-items: center; justify-content: space-between; font-size: 12.5px; color: var(--ink-2); }
.card-close { flex: 0 0 auto; width: 44px; height: 44px; margin: -8px -4px -10px 0; color: var(--ink-2); }
.card h2 { font-size: 15px; font-weight: 650; padding-right: 8px; }
.card-fig { padding: 2px 8px 0 0; font-size: 21px; font-weight: 600; line-height: 1.2; }
.card-fig .unit { font-size: 13.5px; font-weight: 400; color: var(--ink-2); }
.card-sub, .card .note { padding-right: 8px; font-size: 12.5px; color: var(--ink-2); }
.card .note { margin-top: 6px; }
.card dl, .sheet-body dl { display: grid; grid-template-columns: auto 1fr; }
.card dl { margin: 6px 8px 0 0; padding-top: 6px; border-top: 1px solid var(--line); gap: 1px 14px; font-size: 12.5px; }
.card dt { color: var(--ink-2); }
.card dd { margin: 0; text-align: right; font-weight: 560; }
.planets { margin: 6px 8px 0 0; padding: 0; list-style: none; font-size: 12.5px; }
.planets li { display: flex; justify-content: space-between; gap: 10px; }
.planets .d { color: var(--ink-2); text-align: right; }
.card-keys { position: sticky; bottom: -6px; display: flex; gap: 4px; margin: 2px 0 -6px -8px; background: var(--sheet); }
.textkey { min-width: 44px; height: 44px; padding: 0 8px; font-size: 12.5px; color: var(--ink); }

/* a problem with the data is a sentence on the plate */
.notice {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 5;
  width: max-content;
  max-width: min(300px, calc(100% - 32px));
  padding: 10px 14px;
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  background: var(--sheet);
  font-size: 13.5px;
  line-height: 1.4;
  text-align: center;
}

/* ── the caption band: the Reach and the caption ── */

.caption {
  flex: 0 0 auto;
  padding: 4px calc(16px + env(safe-area-inset-right)) 4px calc(16px + env(safe-area-inset-left));
  font-size: 11px;
  line-height: 15px;
  color: var(--ink-2);
}
.reach { height: 33px; }
.reach canvas { display: block; height: 33px; }
/* The caption's height is fixed, whatever it says: its first sentence changes with every move of the
   view, and a caption that grew and shrank would resize the plate, which moves the view. Two lines
   below 640 px hold it at 320 px; one from 640 px (tools/shoot.mjs measures the longest). */
.cap { height: 30px; overflow: hidden; }
/* the last band once the player has gone pads for the home indicator */
.caption:has(+ [hidden]) { padding-bottom: calc(4px + env(safe-area-inset-bottom)); }
@media (min-width: 640px) { .cap { height: 15px; } }

/* ── the player: the date, the transport and the track (the Solar System scale only) ── */

.player {
  flex: 0 0 auto;
  padding: 2px calc(12px + env(safe-area-inset-right)) env(safe-area-inset-bottom) calc(12px + env(safe-area-inset-left));
  border-top: 1px solid var(--line);
}
/* 44 px: the speed key's and Now's hit areas end where the track begins (the track paints over them) */
.time-row { display: flex; align-items: center; gap: 8px; height: 44px; padding: 0 0 0 4px; }
.valid { font-size: 21px; line-height: 1; font-weight: 600; white-space: nowrap; }
.lead { flex: 1 1 auto; min-width: 0; overflow: hidden; font-size: 12.5px; color: var(--ink-2); white-space: nowrap; }
.clk2 { display: none; }
@media (max-width: 439px) { .valid .clk { display: none; } .clk2 { display: inline; } }
.wordkey { position: relative; flex: 0 0 auto; height: 28px; padding: 0 9px; border: 1px solid var(--line-strong); border-radius: 6px; font-size: 12.5px; font-weight: 600; white-space: nowrap; }
.wordkey::before { content: ''; position: absolute; inset: -9px -1px; }
.time-row .textkey { margin-right: -4px; }
.controls { display: flex; align-items: flex-start; }
.tkey { flex: 0 0 auto; width: 44px; height: 44px; color: var(--ink-2); }
.tkey.play { color: var(--page); }
.shutter { width: 32px; height: 32px; border-radius: 8px; background: var(--ink); }
.shutter svg { fill: currentColor; stroke: none; }
.track { position: relative; flex: 1 1 auto; min-width: 0; height: 58px; margin-left: 4px; cursor: pointer; touch-action: none; }
.track canvas { display: block; width: 100%; height: 58px; }
.track:focus-visible { outline-offset: -2px; }
/* no transition, ever, on what carries a step */
.valid, .lead, .track, .track canvas { transition: none; animation: none; }

/* ── the sheets: About, Find, Layers ── */

.sheet { position: fixed; inset: 0; z-index: 20; }
.sheet-panel { position: absolute; inset: 0; display: flex; flex-direction: column; background: var(--sheet); animation: sheet-in 220ms var(--sheet-in); }
@keyframes sheet-in { from { transform: translateY(100%); } }
.sheet-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: env(safe-area-inset-top) calc(8px + env(safe-area-inset-right)) 0 calc(16px + env(safe-area-inset-left));
  border-bottom: 1px solid var(--line);
}
.sheet-head h2 { font-size: 15px; font-weight: 650; }
.sheet-body {
  flex: 1 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0 calc(16px + env(safe-area-inset-right)) calc(16px + env(safe-area-inset-bottom)) calc(16px + env(safe-area-inset-left));
}
.sheet-body section { max-width: 62ch; padding: 12px 0; border-bottom: 1px solid var(--line); }
.sheet-body h3 { margin-bottom: 6px; font-size: 13.5px; font-weight: 650; }
.sheet-body h4 { margin: 12px 0 4px; font-size: 13.5px; font-weight: 600; }
.sheet-body p { margin-bottom: 8px; line-height: 1.5; overflow-wrap: anywhere; }
.sheet-body p:last-child { margin-bottom: 0; }
.sheet-body dl { margin: 0 0 8px; gap: 3px 12px; line-height: 1.45; }
.sheet-body dt { color: var(--ink-2); }
.sheet-body dd { margin: 0; overflow-wrap: anywhere; }
.search-q {
  width: 100%;
  height: 44px;
  margin: 12px 0 4px;
  padding: 0 10px;
  border: 1px solid var(--line-strong);
  border-radius: 6px;
  background: var(--sheet);
  font-size: 16px;            /* the one size off the scale: iOS zooms into a smaller field */
  appearance: none;
}
.search-q::-webkit-search-cancel-button { appearance: none; }   /* no accent cross */
.results { margin: 0; padding: 0; list-style: none; }
.results button { display: flex; flex-direction: column; align-items: flex-start; justify-content: center; width: 100%; min-height: 44px; padding: 4px 0; border-bottom: 1px solid var(--line); text-align: left; }
.results .k { font-size: 11.5px; color: var(--ink-2); }
.results .empty { padding: 12px 0; color: var(--ink-2); }
.layer-row { display: flex; align-items: center; gap: 12px; min-height: 44px; padding: 4px 0; border-bottom: 1px solid var(--line); cursor: pointer; }
.layer-row input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.layer-row .box { flex: 0 0 auto; width: 28px; height: 28px; border: 1px solid var(--line-strong); border-radius: 4px; color: var(--ink); }
.layer-row .box svg { visibility: hidden; }
.layer-row input:checked + .box { border-color: transparent; background: color-mix(in srgb, var(--ink) 12%, transparent); }
.layer-row input:checked + .box svg { visibility: visible; }
.layer-row input:focus-visible + .box { outline: 2px solid var(--ink); outline-offset: 2px; }
.layer-row .t { display: block; }
.layer-row .s { display: block; font-size: 11.5px; color: var(--ink-2); }
.sheet-foot { margin-top: 8px; }

/* ── focus mode: the chrome leaves; the plate, the About key, the caption and the player stay ── */

.leaving { opacity: 0; transition: opacity 160ms var(--draw); }

@media (hover: hover) {
  .keyplate button:hover svg { background: color-mix(in srgb, currentColor 7%, transparent); border-radius: 4px; }
  .scales button:hover, .stamp:hover, .textkey:hover, .tkey:hover, .wordkey:hover, .results button:hover { color: var(--ink); }
  .ghost:hover { opacity: 1; }
}
@media (min-width: 700px) {
  .head, .caption { padding-left: calc(20px + env(safe-area-inset-left)); padding-right: calc(20px + env(safe-area-inset-right)); }
}

/* ── a phone on its side: each band gives the plate its second row ── */

@media (orientation: landscape) and (max-height: 500px) {
  .head { grid-template-columns: max-content minmax(0, 1fr) auto; grid-template-rows: 22px 24px; column-gap: 16px; padding-top: env(safe-area-inset-top); }
  .stamp-home { grid-area: 2 / 1; padding-bottom: 0; }
  .head:has(#stamp-home[hidden]) h1 { grid-row: 1 / 3; align-self: center; }   /* no stamp: the name centers on the words */
  .hkeys { grid-area: 1 / 3 / 3 / 4; }
  .stamp { white-space: nowrap; }
  .scales { grid-area: 1 / 2 / 3 / 3; margin: 0; }
  .caption { padding-top: 2px; padding-bottom: 2px; }
  .cap { height: 15px; }
  .player { display: flex; align-items: center; gap: 8px; padding-top: 0; }
  .time-row { flex: 0 0 auto; height: auto; padding: 0 4px; }
  .controls { flex: 1 1 auto; min-width: 0; align-items: center; }
  .card { max-height: calc(100% - 16px); }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0s !important; transition-duration: 0s !important; scroll-behavior: auto !important; }
}
