/* ==========================================================================
   LEARN PAGES — /screens · /manual · /glossary · /shortcuts · /start
   --------------------------------------------------------------------------
   Loaded only by the five pages that frontend/pages_learn.js serves, via
   LEARN_SHEET in app/pages_registry.py. Linked AFTER static/instrument.css and
   static/pages.css, which is what lets an equal-specificity rule here opt a
   specific element out of a blanket one.

   WHY EVERY CLASS HERE IS `pln` + camelCase, WITH NO HYPHEN ANYWHERE
   static/obsidian_orchid.css restyles by SUBSTRING with !important —
   `[class*="-status"]`, `-tooltip`, `-chip`, `-tag`, `-tile`, `-pane`,
   `-line`, `-path` — and uppercases anything matching `[class$="-title"]`,
   `-label`, `-header`, `-heading`, `-caption`, `-kicker`. instrument.css does
   the same trick for its component ladder. A name containing no hyphen at all
   is unmatchable by that entire family BY CONSTRUCTION, so `plnStatusFlag`
   cannot accidentally inherit a pill skin and `plnSectionTitle` cannot be
   force-uppercased.

   The corollary: a `pln*` class gets NOTHING for free. Where an element wants
   the house surface it also carries the hyphenated kit class that grants it —
   `pk-panel`, `pk-card`, `pk-badge` — and the `pln*` class only adds layout.
   That is deliberate: two names, two jobs, no surprises.

   NO RAW HEX. Every colour resolves through an --i-* token. Neutral alpha
   veils follow instrument.css's own convention and carry no hue.
   ========================================================================== */

/* ==========================================================================
   1 — SHARED PAGE FURNITURE
   ========================================================================== */

/* The lede paragraph on these pages is long-form prose, not a marketing line. */
.plnLede { max-width: 78ch; }

/* A sticky control strip: search, filters, and the live result count.
   `top: 0` was wrong. .pk-masthead is ALSO sticky at top: 0, at z-index 30
   against this strip's 3 — so on any scroll the toolbar slid underneath the
   masthead and the search field it contains became unreachable exactly when a
   reader scrolling a 62-row index most wants it. It now parks below the
   masthead, against the height pages.css DECLARES for it rather than a height
   measured at runtime: this build's verification pane never fires rAF or
   ResizeObserver, so a JS-measured offset would be a number nobody can check. */
.plnToolbar {
  position: sticky;
  top: var(--pk-masthead-h);
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: 0 0 24px;
  padding: 12px;
  border: 1px solid var(--i-hair);
  border-radius: var(--i-r-control);
  background: color-mix(in srgb, var(--i-surface-1) 92%, transparent);
  backdrop-filter: blur(10px);
  box-shadow: var(--i-elev-1);
}

.plnSearch {
  flex: 1 1 240px;
  min-width: 0;
  height: 34px;
  padding: 0 12px;
  border: 1px solid var(--i-hair-strong);
  border-radius: var(--i-r-control);
  background: var(--i-field-bg);
  color: var(--i-ink-1);
  font-family: var(--oo-font-ui);
  font-size: var(--i-t-body);
}
.plnSearch::placeholder { color: var(--i-ink-4); }
.plnSearch:focus-visible { outline: 2px solid var(--i-accent-edge); outline-offset: 1px; }

.plnFilters { display: flex; gap: 6px; flex-wrap: wrap; min-width: 0; }

/* Filter pills. `plnFilter` is the button; `aria-pressed` carries the state, so
   the selected look is driven by the accessibility attribute rather than by a
   second class that could disagree with it. */
.plnFilter {
  border: 1px solid var(--i-hair-strong);
  border-radius: var(--i-r-pill);
  background: var(--i-control-bg);
  color: var(--i-ink-2);
  font-family: var(--oo-font-ui);
  font-size: var(--i-t-xs);
  letter-spacing: var(--i-track-label);
  text-transform: uppercase;
  font-weight: 600;
  padding: 5px 11px;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--i-dur-fast) var(--i-ease-out),
              color var(--i-dur-fast) var(--i-ease-out);
}
.plnFilter:hover { background: var(--i-control-bg-hover); color: var(--i-ink-1); }
.plnFilter[aria-pressed="true"] {
  color: var(--i-ink-on-accent);
  background: var(--i-orchid-deep);
  border-color: var(--i-accent-edge);
}
.plnFilter:focus-visible { outline: 2px solid var(--i-accent-edge); outline-offset: 2px; }

.plnCount {
  margin-left: auto;
  color: var(--i-ink-3);
  font-size: var(--i-t-sm);
  white-space: nowrap;
}

/* ==========================================================================
   2 — /screens · the A–Z index
   ========================================================================== */

.plnAlpha {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 0 0 18px;
}
.plnAlpha a {
  min-width: 24px;
  text-align: center;
  padding: 2px 5px;
  border-radius: var(--i-r-chip);
  color: var(--i-ink-3) !important;
  font-family: var(--oo-font-data);
  font-size: var(--i-t-sm);
  text-decoration: none;
}
.plnAlpha a:hover { color: var(--i-orchid-bright) !important; background: var(--i-control-bg); }
.plnAlpha span {
  min-width: 24px;
  text-align: center;
  padding: 2px 5px;
  color: var(--i-ink-4);
  font-family: var(--oo-font-data);
  font-size: var(--i-t-sm);
}

.plnLetter {
  margin: 40px 0 16px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--i-hair);
  color: var(--i-ink-3);
  font-family: var(--oo-font-data);
  font-size: var(--i-t-sm);
  letter-spacing: var(--i-track-label);
  /* Anchor targets land under BOTH sticky strips without this: the masthead and
     the toolbar parked below it, plus a step of breathing room. Written from
     the same declared masthead height the toolbar uses, so the three cannot
     drift apart. */
  scroll-margin-top: calc(var(--pk-masthead-h) * 2 + 16px);
}
.plnLetter:first-child { margin-top: 0; }

/* ---- the directory ------------------------------------------------------
   /screens is the largest single surface on the site — 62 screens, each with a
   mnemonic, a name, a purpose and a provenance line. As a flat list of 62
   hairline-separated rows it was a document. As cards it is a directory: the
   eye lands on a bounded object, reads the mono mnemonic first because it is
   the only monospace thing in the card, and the purpose second.

   Two columns, not four. A 400px floor means the purpose sentence still gets a
   readable measure and each letter group fills its row instead of leaving one
   card stranded beside three gaps. */
.plnIndex {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(400px, 100%), 1fr));
  gap: 12px;
  align-items: stretch;
}

.plnIndex > li {
  min-width: 0;
  border: 1px solid var(--i-hair);
  border-radius: var(--i-r-card);
  background: var(--i-surface-1);
  transition: border-color var(--i-dur-fast) var(--i-ease-out),
              background var(--i-dur-fast) var(--i-ease-out),
              box-shadow var(--i-dur-fast) var(--i-ease-out),
              transform var(--i-dur-fast) var(--i-ease-out);
}
.plnIndex > li:hover {
  border-color: var(--i-accent-edge-soft);
  background: var(--i-surface-2);
  transform: translateY(-2px);
  box-shadow: var(--i-elev-2);
}
/* The card is not itself a link — the mnemonic inside it is — so keyboard focus
   lands on .plnCode. Mirroring the hover state on :focus-within keeps the card
   under a tabbing reader in exactly the same place as under a mouse. */
.plnIndex > li:focus-within {
  border-color: var(--i-accent-edge);
  background: var(--i-surface-2);
}

/* Stacked, not two-column: inside a 400px card a 92px gutter left the purpose
   sentence a 280px measure and broke it into six lines. */
.plnRow {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 8px;
  padding: 18px 20px 16px;
  align-items: start;
}

/* The mnemonic sits on the card's top line with its status badge beside it. The
   markup wraps the badge in an unclassed div, so `display: contents` lifts the
   badge into this flex row instead of parking it on a line of its own — no
   markup change, which this package is not allowed to make anyway. */
.plnRow > div:first-child {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  min-width: 0;
}
.plnRow > div:first-child > div { display: contents; }

/* The mnemonic. Mono FACE without the `mono` CLASS: `#app-root .mono` is
   `color: var(--i-ink-1) !important`, which would override the accent colour
   this element needs to read as a link. It is the only monospace thing on the
   card, which is what makes it the first thing the eye lands on. */
.plnCode {
  font-family: var(--oo-font-data);
  font-size: var(--i-t-md);
  font-weight: 600;
  color: var(--i-orchid-bright) !important;
  text-decoration: none;
  letter-spacing: 0.04em;
}
.plnCode:hover { text-decoration: underline; text-underline-offset: 3px; }

.plnRowMain { min-width: 0; }

/* Sans for the title and the blurb — the deliberate counterpart to the mono
   mnemonic above. Two faces doing two jobs is the whole typographic system. */
.plnName {
  color: var(--i-ink-1);
  font-size: var(--i-t-md);
  font-weight: 600;
  letter-spacing: var(--i-track-tight);
  line-height: var(--i-lh-snug);
}

.plnPurpose {
  margin: 6px 0 0;
  color: var(--i-ink-2);
  font-size: var(--i-t-body);
  line-height: var(--i-lh-body);
  max-width: 72ch;
}

.plnMeta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--i-hair);
  color: var(--i-ink-3);
  font-size: var(--i-t-xs);
}

/* The taxonomy path — "Workspace · Group". Monospace, because it is a location
   rather than a sentence, and because it makes the card's footer scannable
   down a column of forty of them. */
.plnMeta > span:first-child {
  font-family: var(--oo-font-data);
  letter-spacing: 0.02em;
  color: var(--i-ink-3);
}
.plnMeta a { color: var(--i-ink-3) !important; text-decoration: underline; text-underline-offset: 2px; }
.plnMeta a:hover { color: var(--i-orchid-bright) !important; }

.plnDot { color: var(--i-ink-4); }

/* Retired / merged. Not hidden, not greyed into illegibility: these commands
   still route, and a reader who has one bookmarked needs to be told what
   happened to it rather than shown nothing. */
.plnGone .plnCode { color: var(--i-ink-3) !important; }
.plnGone .plnName { color: var(--i-ink-2); }

/* ==========================================================================
   3 — /manual · a page per screen
   ========================================================================== */

.plnManualGrid {
  display: grid;
  grid-template-columns: 210px minmax(0, 1fr);
  gap: 28px;
  align-items: start;
}

.plnSideNav {
  position: sticky;
  top: 12px;
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  border-right: 1px solid var(--i-hair);
  padding-right: 14px;
}
.plnSideNav ul { list-style: none; margin: 0 0 14px; padding: 0; }
.plnSideNav li { margin: 0; }
.plnSideNav a {
  display: block;
  padding: 3px 0;
  color: var(--i-ink-3) !important;
  font-size: var(--i-t-sm);
  text-decoration: none;
}
.plnSideNav a:hover { color: var(--i-orchid-bright) !important; }
.plnSideNavHead {
  margin: 0 0 8px;
  color: var(--i-ink-3);
  font-size: var(--i-t-xs);
  letter-spacing: var(--i-track-label);
  text-transform: uppercase;
  font-weight: 600;
}

/* /manual has no toolbar — only the masthead is sticky here, so one masthead of
   clearance plus a step is exactly right. 20px was not: a deep link from
   /screens landed with the entry's own heading hidden behind the masthead. */
.plnEntry {
  margin: 0 0 40px;
  scroll-margin-top: calc(var(--pk-masthead-h) + 16px);
}
.plnEntry:last-child { margin-bottom: 0; }

.plnEntryHead {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin: 0 0 4px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--i-hair);
}
.plnEntryHead h2, .plnEntryHead h3 { margin: 0; font-size: var(--i-t-lg); color: var(--i-ink-1); }

.plnBlock { margin: 14px 0 0; }
.plnBlockHead {
  margin: 0 0 4px;
  color: var(--i-ink-3);
  font-size: var(--i-t-xs);
  letter-spacing: var(--i-track-label);
  text-transform: uppercase;
  font-weight: 600;
}
.plnBlock p { margin: 0; max-width: 82ch; color: var(--i-ink-2); }
.plnBlock ul { margin: 0; padding-left: 18px; max-width: 82ch; }
.plnBlock li { margin: 0 0 5px; color: var(--i-ink-2); }

/* THE SECTION THIS WHOLE PAGE EXISTS FOR. Amber rather than red: a documented
   limit is not an error state, and painting it as one trains readers to skip
   it. It is set apart because it is the part a competitor's docs omit. */
.plnLimits {
  margin: 16px 0 0;
  padding: 12px 14px;
  border-left: 2px solid var(--i-amber);
  border-radius: 0 var(--i-r-control) var(--i-r-control) 0;
  background: color-mix(in srgb, var(--i-amber-wash) 55%, transparent);
}
.plnLimits .plnBlockHead { color: var(--i-amber); }
.plnLimits ul { margin: 0; padding-left: 18px; }
.plnLimits li { margin: 0 0 5px; color: var(--i-ink-2); }
.plnLimits li:last-child { margin-bottom: 0; }

/* An honestly undocumented screen. Dashed, like every other "nothing here yet"
   surface in this product, so it reads as a state rather than as content. */
.plnUndocumented {
  padding: 12px 14px;
  border: 1px dashed var(--i-hair-strong);
  border-radius: var(--i-r-control);
  color: var(--i-ink-3);
  font-size: var(--i-t-body);
}

/* ==========================================================================
   4 — /glossary
   ========================================================================== */

.plnTerms { list-style: none; margin: 0; padding: 0; }
.plnTerms > li {
  padding: 16px 0;
  border-bottom: 1px solid var(--i-hair);
  /* Deep links from tooltips elsewhere land here. /glossary stacks the masthead
     and the toolbar, so the clearance is two of them plus a step — derived from
     the same declared height, never a magic number. */
  scroll-margin-top: calc(var(--pk-masthead-h) * 2 + 16px);
}
.plnTerms > li:last-child { border-bottom: none; }

.plnTermHead {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
.plnTerm {
  color: var(--i-ink-1);
  font-size: var(--i-t-md);
  font-weight: 600;
}
/* ink-3, not ink-4: an alias is a word a reader has to read, and ink-4 is
   3.03:1 on the void — the rule colour, below the AA floor for text. */
.plnAlias { color: var(--i-ink-3); font-size: var(--i-t-sm); }

/* The permalink handle. Visible only on hover or keyboard focus, so 40 of them
   do not turn the page into a field of hashes — but always reachable by tab. */
.plnPermalink {
  color: var(--i-ink-4) !important;
  font-family: var(--oo-font-data);
  font-size: var(--i-t-sm);
  text-decoration: none;
  opacity: 0;
  transition: opacity var(--i-dur-fast) var(--i-ease-out);
}
.plnTerms > li:hover .plnPermalink,
.plnPermalink:focus-visible { opacity: 1; }
.plnPermalink:hover { color: var(--i-orchid-bright) !important; }

.plnDef { margin: 5px 0 0; max-width: 82ch; color: var(--i-ink-2); }

/* A term arrived at by deep link gets a one-beat highlight rather than a
   permanent one, so a shared link does not leave the page looking edited. */
.plnTerms > li:target { background: var(--i-orchid-wash); box-shadow: -10px 0 0 var(--i-orchid-wash), 10px 0 0 var(--i-orchid-wash); }

/* ==========================================================================
   5 — /shortcuts
   ========================================================================== */

.plnKeyGroup { margin: 0 0 8px; }

.plnKeyRow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 6px 18px;
  align-items: center;
  padding: 9px 4px;
  border-bottom: 1px solid var(--i-hair);
}
.plnKeyRow:last-child { border-bottom: none; }

.plnKeyWhat { min-width: 0; color: var(--i-ink-1); font-size: var(--i-t-body); }
.plnKeyWhat em {
  display: block;
  margin-top: 3px;
  color: var(--i-ink-3);
  font-size: 11px;
  font-style: normal;
  max-width: 76ch;
}

.plnKeyCaps { display: inline-flex; align-items: center; gap: 5px; flex-wrap: wrap; justify-content: flex-end; }
.plnThen { color: var(--i-ink-3); font-size: var(--i-t-xs); }

.plnTags { display: inline-flex; gap: 6px; margin-left: 8px; vertical-align: middle; }

/* Printing a key map is a real thing people do. Drop the chrome, keep the keys. */
@media print {
  .pk-masthead, .pk-footer, .plnToolbar, .plnSideNav, .pk-skip-inline { display: none !important; }
  .plnKeyRow { break-inside: avoid; }
}

/* ==========================================================================
   6 — /start
   ========================================================================== */

.plnPath { list-style: none; margin: 0; padding: 0; counter-reset: plnstep; }

.plnStep {
  position: relative;
  padding: 0 0 24px 46px;
  /* The spine. A pseudo-element rather than a border on the li so the last
     step can stop the line at its own marker instead of running past it. */
}
.plnStep::before {
  counter-increment: plnstep;
  content: counter(plnstep);
  position: absolute;
  left: 0;
  top: 0;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: var(--i-r-pill);
  border: 1px solid var(--i-accent-edge);
  background: var(--i-orchid-wash);
  color: var(--i-ink-1);
  font-family: var(--oo-font-data);
  font-size: var(--i-t-sm);
  font-weight: 600;
}
.plnStep::after {
  content: "";
  position: absolute;
  left: 14px;
  top: 32px;
  bottom: 4px;
  width: 1px;
  background: var(--i-hair);
}
.plnStep:last-child::after { display: none; }

.plnStepTitle {
  margin: 3px 0 6px;
  color: var(--i-ink-1);
  font-size: var(--i-t-md);
  font-weight: 600;
}
.plnStep p { margin: 0 0 8px; max-width: 80ch; }
.plnStep p:last-child { margin-bottom: 0; }

.plnDo {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border: 1px solid var(--i-accent-edge-soft);
  border-radius: var(--i-r-control);
  background: var(--i-control-bg);
  color: var(--i-ink-1) !important;
  font-size: var(--i-t-body);
  text-decoration: none;
}
.plnDo:hover { background: var(--i-control-bg-hover); border-color: var(--i-accent-edge); }
.plnDo code {
  font-family: var(--oo-font-data);
  font-size: var(--i-t-sm);
  color: var(--i-orchid-bright);
}

.plnAside {
  margin: 8px 0 0;
  padding: 10px 12px;
  border-left: 2px solid var(--i-hair-strong);
  color: var(--i-ink-3);
  font-size: var(--i-t-sm);
  max-width: 80ch;
}

/* ==========================================================================
   7 — MOTION
   --------------------------------------------------------------------------
   instrument.css already flattens every transition-duration under #app-root
   inside its own reduced-motion guard, but a `transform` on :hover is not a
   duration — with the transition killed it becomes an INSTANT 2px jump, which
   is still motion and still exactly what the preference asks not to happen. So
   the displacement itself is removed, not just its easing. Both switches are
   honoured: the OS preference and the in-app `data-motion` setting.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .plnIndex > li { transition: none; }
  .plnIndex > li:hover { transform: none; }
  .plnPermalink { transition: none; }
}
:root[data-motion="reduced"] .plnIndex > li { transition: none; }
:root[data-motion="reduced"] .plnIndex > li:hover { transform: none; }

/* ==========================================================================
   8 — NARROW VIEWPORTS
   ========================================================================== */

@media (max-width: 860px) {
  .plnManualGrid { grid-template-columns: minmax(0, 1fr); gap: 18px; }
  .plnSideNav {
    position: static;
    max-height: none;
    border-right: none;
    border-bottom: 1px solid var(--i-hair);
    padding: 0 0 12px;
  }
  .plnSideNav ul { display: flex; flex-wrap: wrap; gap: 4px 12px; }
}

@media (max-width: 620px) {
  .plnRow { grid-template-columns: minmax(0, 1fr); }
  .plnKeyRow { grid-template-columns: minmax(0, 1fr); }
  .plnKeyCaps { justify-content: flex-start; }
  .plnCount { margin-left: 0; }
}
