/* ==========================================================================
   hi-states.css — the four states, said one way.
   ------------------------------------------------------------------------
   Every dynamic surface on this site eventually says one of four things:

     LOADING  the shape of the answer, before the answer
     EMPTY    there is nothing here, and that is a fact, not a failure
     ERROR    it did not load, here is what you can do
     STALE    this IS the answer, but the snapshot behind it has aged

   Before this file each page said them in its own dialect: five spellings
   of "no results", three greys of skeleton, a different error voice per
   app. This sheet is the vocabulary. Pages keep their OWN WORDS — the
   classes here change the clothing, never the copy.

   ANATOMY
     .hi-sk                 one skeleton bar (loading)
     .hi-sk-rows            a stack of bars that matches a list's rhythm
     [data-hi-loading]      a region announcing itself as loading
     .hi-empty              the empty note — serif, upright, open
     .hi-error              the error note — ink, coral hairline-left
     .hi-error-do           the one thing the reader can do about it
     (stale lives in hi-receipt.css as [data-receipt-stale], because a
      stale mark is a receipt with a date that has gone off, not a new
      component.)

   NO ITALICS. NO GOLD (the ◷ in the stale chip is the only exception and
   it belongs to hi-receipt.css). Skeletons reserve the exact box the real
   content will occupy, so nothing shifts when the answer lands.

   TOKENS: each colour reads the host page's local name first and falls
   through the known per-surface dialects to the canonical --hi- token.
   Load this file AFTER hi-tokens.css and after the page's own sheet.
   ========================================================================== */

:root{
  --hs-ink:    var(--ink,      var(--do-ink,      var(--rw-ink,      var(--hi-ink, #0d1f3c))));
  --hs-muted:  var(--muted,    var(--do-muted,    var(--rw-muted,    var(--hi-muted, #556a80))));
  --hs-line:   var(--hairline, var(--do-hairline, var(--rw-hairline, var(--hi-hair, #e4dac7))));
  --hs-edge:   var(--border,   var(--do-border,   var(--rw-border,   var(--hi-line, #d7cbb7))));
  --hs-surf1:  var(--card,     var(--do-surface-1, var(--rw-card,    var(--hi-surface-1, #fffaf1))));
  --hs-blue:   var(--blue,     var(--do-accent,   var(--rw-blue,     var(--hi-blue, #1f5fbf))));
  --hs-coral:  var(--coral,    var(--do-coral,    var(--rw-coral,    var(--hi-coral, #b34e3e))));
  --hs-serif:  var(--serif,    var(--hi-serif, 'Newsreader', Georgia, serif));
  --hs-mono:   var(--mono,     var(--hi-mono, 'JetBrains Mono', ui-monospace, monospace));

  /* the skeleton fill. It is INK AT WASH STRENGTH, not a grey: a grey bar
     on parchment reads as a hole, and the site has no holes above the
     fold. Measured to sit between surface-1 and surface-3. */
  --hs-sk:      rgba(13,31,60,.085);
  --hs-sk-glint:rgba(255,255,255,.55);
}
:root[data-theme="dark"]{
  --hs-sk:      rgba(157,184,221,.13);
  --hs-sk-glint:rgba(198,214,234,.16);
}

/* ==========================================================================
   1. LOADING — one shimmer, everywhere
   --------------------------------------------------------------------------
   A skeleton bar is a PROMISE ABOUT LAYOUT. Give it the width and height of
   the thing it stands in for and the page does not move when the content
   arrives. --hi-sk-w / --hi-sk-h are the two dials.

   The glint is the same sweep hi-motion.js gives [data-fx-shimmer]; this
   file re-states it under its own keyframe name so a page that never loads
   hi-motion.js still gets it, and so the two can never drift out of phase
   with each other on a page that loads both (identical duration + easing).
   ========================================================================== */

.hi-sk{
  display:block;
  position:relative;
  overflow:hidden;
  box-sizing:border-box;
  width:var(--hi-sk-w, 100%);
  height:var(--hi-sk-h, .78em);
  min-height:8px;
  border-radius:5px;
  background:var(--hs-sk);
  /* a skeleton is furniture, not content: it must never be read aloud */
  color:transparent;
  user-select:none;
  pointer-events:none;
}
.hi-sk::after{
  content:"";
  position:absolute;
  inset:0;
  transform:translateX(-100%);
  background:linear-gradient(90deg, transparent, var(--hs-sk-glint), transparent);
  animation:hi-sk-sweep 1.5s ease-in-out infinite;
}
@keyframes hi-sk-sweep{ to{ transform:translateX(100%) } }

/* inline variant — a bar that sits in a line of text, holding a number's
   width open. Baseline-aligned so the row's leading does not change. */
.hi-sk.is-inline{
  display:inline-block;
  vertical-align:-.14em;
  width:var(--hi-sk-w, 3.2em);
  height:var(--hi-sk-h, .72em);
  border-radius:4px;
}
/* a block that stands in for a card or a chart */
.hi-sk.is-block{ height:var(--hi-sk-h, 96px); border-radius:10px }
/* a circle standing in for a crest or a mug */
.hi-sk.is-round{ border-radius:999px; width:var(--hi-sk-w, 34px); height:var(--hi-sk-h, 34px) }

/* the stack. Rows alternate width so the block reads as language rather
   than as a bar chart; the last row is short, the way a paragraph ends. */
.hi-sk-rows{
  display:grid;
  gap:var(--hi-sk-gap, 10px);
  padding:var(--hi-sk-pad, 4px 0);
  margin:0;
}
.hi-sk-rows .hi-sk:nth-child(3n+2){ width:92% }
.hi-sk-rows .hi-sk:nth-child(3n+3){ width:78% }
.hi-sk-rows .hi-sk:last-child{ width:54% }

/* a region that is loading gets ONE announcement, not one per bar */
[data-hi-loading]{ position:relative }
[data-hi-loading] > .hi-sk-label,
.hi-sk-label{
  display:block;
  font-family:var(--hs-mono);
  font-size:.6rem;
  font-weight:500;
  font-style:normal;
  letter-spacing:.055em;
  color:var(--hs-muted);
  padding:0 0 10px;
}

/* Reduced motion: keep the bars, drop the sweep. The bars still carry the
   layout promise, which is the part that matters. */
@media (prefers-reduced-motion: reduce){
  .hi-sk::after{ animation:none; opacity:0 }
}

/* ==========================================================================
   2. EMPTY — the established grammar, once
   --------------------------------------------------------------------------
   Serif, upright, muted, open tracking, generous top and bottom. An empty
   state is a sentence the page means; it is not an error and it does not
   get an icon, a border, a button or a shrug.
   ========================================================================== */

.hi-empty{
  display:block;
  margin:0;
  padding:var(--hi-empty-pad, 26px 4px 28px);
  font-family:var(--hs-serif);
  font-style:normal;
  font-weight:500;
  font-size:var(--hi-empty-size, .95rem);
  line-height:1.6;
  letter-spacing:.012em;
  color:var(--hs-muted);
  text-align:var(--hi-empty-align, left);
  text-wrap:pretty;
}
/* the dense variant — inside a drawer, a table cell, a rail */
.hi-empty.is-tight{
  --hi-empty-pad:13px 2px 14px;
  --hi-empty-size:.86rem;
}
/* an empty state may carry ONE secondary line telling the reader what
   would fill it. Sans, smaller, still muted — never a call to action. */
.hi-empty > .hi-empty-hint{
  display:block;
  margin-top:7px;
  font-family:inherit;
  font-size:.82em;
  letter-spacing:.02em;
  color:var(--hs-muted);
  opacity:.82;
}

/* ==========================================================================
   3. ERROR — a plain sentence with a coral rule down its left
   --------------------------------------------------------------------------
   No icon, no red panel, no exclamation. The rule is the signal; the
   sentence is the content. The rule is 2px because --hs-line is a grouping
   hairline and this is not grouping, it is flagging.

   An error MUST say what the reader can do, when the page has an answer.
   .hi-error-do is that clause.
   ========================================================================== */

.hi-error{
  display:block;
  margin:var(--hi-error-margin, 14px 0);
  padding:var(--hi-error-pad, 2px 0 3px 13px);
  border-left:2px solid var(--hs-coral);
  font-family:inherit;
  font-style:normal;
  font-weight:500;
  font-size:var(--hi-error-size, .84rem);
  line-height:1.58;
  letter-spacing:.005em;
  color:var(--hs-ink);
  text-wrap:pretty;
}
.hi-error .hi-error-do,
.hi-error-do{
  display:block;
  margin-top:5px;
  font-size:.92em;
  color:var(--hs-muted);
}
/* the retry affordance, when the page has one. Blue carries the action;
   the rule stays coral, because the rule is the diagnosis. */
.hi-error a,
.hi-error button.hi-error-retry{
  font:inherit;
  font-size:1em;
  color:var(--hs-blue);
  background:none;
  border:0;
  padding:0;
  cursor:pointer;
  text-decoration:underline;
  text-underline-offset:.16em;
}
.hi-error a:focus-visible,
.hi-error button.hi-error-retry:focus-visible{
  outline:2px solid var(--hs-blue);
  outline-offset:2px;
  border-radius:2px;
}

/* the mono variant, for surfaces whose whole voice is mono (the draft
   board drawer, the team hub). Same rule, same colour, page's own type. */
.hi-error.is-mono{
  font-family:var(--hs-mono);
  font-size:var(--hi-error-size, .7rem);
  letter-spacing:.03em;
  line-height:1.65;
}

/* ==========================================================================
   4. STALE
   --------------------------------------------------------------------------
   Lives in hi-receipt.css: see [data-receipt-stale]. A stale mark is the
   page's existing receipt with its date gone cold, so it must be the same
   object — a second component would let the two drift apart.

   RULE OF ADOPTION: only mark stale where the page ALREADY knows its
   snapshot date. This sheet defines no threshold and no clock. If a page
   cannot say when its data was taken, it does not get a stale chip.
   ========================================================================== */

@media print{
  .hi-sk{ display:none }
}

/* =============================================================================
   .hi-faq — the small answers block.

   Four routes carry a short FAQ because readers arrive on them from a typed
   question, and the page should answer it in two sentences before it draws
   anything. The same markup is mirrored in FAQPage JSON-LD on each page, so
   what a search engine reads and what a reader reads are the same words.
   No italics, no gold; ink and blue only.
   ============================================================================= */
.hi-faq {
  margin: 2.8rem 0 0;
  border-top: 1px solid var(--hi-hair);
  padding-top: 1.4rem;
}
.hi-faq > h2 {
  font: 700 clamp(1.15rem, 2.1vw, 1.5rem)/1.2 var(--hi-serif, "Newsreader", Georgia, serif);
  letter-spacing: -.012em;
  margin: 0 0 .3rem;
  color: var(--hi-ink);
}
.hi-faq > p.hi-faq-lede {
  font: 400 .9rem/1.55 var(--hi-serif, "Newsreader", Georgia, serif);
  color: var(--hi-muted);
  margin: 0 0 1.1rem;
  max-width: 62ch;
}
.hi-faq-list {
  display: grid;
  gap: .7rem;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.hi-faq-item {
  border: 1px solid var(--hi-line);
  border-radius: 13px;
  background: var(--hi-surface-1);
  padding: .9rem 1rem 1rem;
}
.hi-faq-item h3 {
  font: 700 .88rem/1.35 var(--hi-sans, system-ui, sans-serif);
  margin: 0 0 .38rem;
  color: var(--hi-ink);
}
.hi-faq-item p {
  font: 400 .88rem/1.55 var(--hi-serif, "Newsreader", Georgia, serif);
  margin: 0;
  color: var(--hi-ink-2);
}
.hi-faq-item p a { color: var(--hi-blue); }
.hi-faq em, .hi-faq i, .hi-faq cite { font-style: normal; }
