/* public/src/css/sections.css
   The tools' own styles. Filled by Tasks 4-8. Every colour here is a
   semantic alias (--ink, --panel, ...), never a raw hex - see tokens.css
   and test/shell.test.js. Sky Watch, Field Ops and the Case File each wrap
   their controls in one cards.css .card - see cards.css's own note on why
   the fill alone (--panel is only 1.16 on --void) never carries the "this
   is a separate object" read; the border, radius and shadow do that work. */

/* ── notices: every failure and empty state, from notices.js ──
   Reported material: the station reporting on itself, so it is boxed like
   any other reported graphic. The heading and body are --ink; the
   handwritten line underneath is real Marginalia (.tapenote), never --ink,
   because that line is the bloke talking, not the instrument. #notices sits
   empty most of the time, so it takes no space and never reads as a broken
   box waiting for content. */
#notices:empty{display:none}
.notice{
  background:var(--panel);border:1px solid var(--ink);
  border-radius:var(--radius);
  padding:.9rem 1.1rem;margin-bottom:1.25rem;
}
.notice .n-head{
  font-family:var(--f-data);font-size:var(--step--1);letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink);margin:0 0 .5rem;
}
.notice .n-body{color:var(--ink);margin:.4rem 0}
.notice .n-body.dim{color:var(--ink-dim)}
/* The failing response body, verbatim and escaped (see notices.js) - real
   server text, so it stays monospace, never smaller than the data type. */
.notice .n-detail{
  font-family:var(--f-data);font-size:var(--step--1);color:var(--ink-dim);
  white-space:pre-wrap;word-break:break-word;overflow-x:auto;
  background:var(--void);border:1px solid var(--edge);
  padding:.5em .7em;margin:.5em 0;
}
/* This <pre> only exists when something is broken (notices.js's own
   noticeMarkup()), which is why the tab-stop sweep for the rest of the site
   missed it: overflow-x:auto is the same mechanism that put .file in the
   tab order on /case-file/ (see that rule's own note), but unlike .file this
   one SHOULD stay focusable - a long error detail that scrolls is a
   legitimately reachable control, not an accident. cards.css's
   a/button/summary focus rule does not reach a <pre>, so without this it
   showed the browser's default ring instead of the site's. */
.notice .n-detail:focus-visible{outline:2px solid var(--signal);outline-offset:2px}
.notice .n-hand{margin:.7em 0 0}

/* ── Marginalia inside a notice or a control row: the bloke, on a strip of
   masking tape. Same voice as .hand (page.css), different context, so it
   gets its own class rather than borrowing tape markup that does not exist
   on the newspaper pages. ── */
.tapenote{
  font-family:var(--f-hand);font-size:var(--step-1);line-height:1.25;
  color:var(--signal);transform:rotate(-.6deg);margin:0;
}

/* ── Sky Watch: the scope, its readout, and the control row ── */
.scopewrap{
  display:flex;flex-direction:column;align-items:center;gap:.5rem;
  max-width:320px;margin:1.25rem 0;
}
.scopewrap .cutline{width:100%}

/* The scope is a boxed news graphic (Reported), not glass - the rack's CRT
   is retired with the rack. #scope is rendered by scope.js's scopeMarkup();
   everything below styles that markup. scope.js names no colour token
   itself - every colour here comes from the object-class and scope-face
   tokens added in tokens.css, so this rule set is the only place a change
   to scope.js's four classes has to be made. */
#scope{
  display:block;width:min(260px,70vw);aspect-ratio:1;
  border-radius:50%;background:var(--panel);border:2px solid var(--ink);
  cursor:crosshair;touch-action:none;
}
/* Crosshair, not grab: this is a scope, not a map. The grabbing hand
   appears only while a pan is genuinely under way (initScope() in
   scope.js allows that only above 1x zoom). */
#scope.panning{cursor:grabbing}

/* Grid rings, crosshairs and the rim are graphics, not text, so they may
   sit below the 4.5:1 text floor - only --ink-dim itself, dimmed further
   with opacity so the grid recedes behind the blips it exists to place.
   Every one carries vector-effect="non-scaling-stroke" so zooming enlarges
   the geometry without also thickening the line weight. */
#scope .ring{fill:none;stroke:var(--ink-dim);stroke-width:1;stroke-dasharray:1 3;stroke-opacity:.5}
#scope .ring.rim{stroke-dasharray:none;stroke-width:1.6;stroke-opacity:.85}
#scope .cross{stroke:var(--ink-dim);stroke-width:1;stroke-opacity:.3}

/* Tick numbers (30/60) and the cardinal letters are real text, so they take
   the text floor, not the graphics exemption above - measured as "scope:
   labels and ticks" in test/contrast.js. The tick labels counter-scale via
   a transform scope.js sets per zoom level, which is what keeps them a
   constant size at any zoom rather than shrinking to nothing. */
#scope .tick,#scope .lbl{font-family:var(--f-data);font-size:28px;fill:var(--ink-dim)}
#scope .lbl{font-size:30px}

/* Future-track trails: dotted, dim, drawn for at most the first six cards -
   see scope.js. Never solid, so a trail is never mistaken for a live blip. */
#scope .trail{fill:none;stroke:var(--ink-dim);stroke-width:1;stroke-dasharray:2 3;stroke-opacity:.6}

/* Object classes - measured in test/contrast.js at the 3:1 graphic floor
   (and the 4.5:1 text floor, for the same four used as name text elsewhere),
   against --panel. These are the SAME four tokens the front page's own
   #scope shares, so nothing here introduces a new pair to measure. Debris
   is deliberately a hollow ring rather than a filled dot: fill:none is set
   per-blip in the markup (scope.js), so class is never encoded by colour
   alone even for a viewer who cannot distinguish the hues. */
#scope .blip.pay{fill:var(--sky)}
#scope .blip.star{fill:var(--iris)}
#scope .blip.rkt{fill:var(--amber)}
#scope .blip.deb{stroke:var(--rose);stroke-width:1.4}
/* Carded contacts are already drawn larger (scope.js bakes the bigger
   radius into the markup) - that size difference alone is what makes them
   findable, so no extra styling rides on .carded here. */
#scope .blip.sel{stroke:var(--signal);stroke-width:1.6}

/* The sweep: one rotating wedge, not per-blip lighting - 1,400 class
   toggles a frame is not a real option. Driven entirely by scope.js's
   startSweep() via requestAnimationFrame; this rule only says what it
   looks like, never how it moves. No CSS animation, on purpose: OS-level
   reduced-motion silently freezes CSS animations with no signal, so
   startSweep() checks prefers-reduced-motion itself instead. */
#scope .sweep{fill:var(--ink-dim);opacity:.5;pointer-events:none}

/* The readout beside/under the scope - Reported, set in body type via the
   shared .data class (page.css). */
.tele{color:var(--ink);line-height:1.6;margin-top:1rem}
.tele p{margin:.25rem 0}
.tele .hi{color:var(--ink);font-weight:600}
.tele .dim{color:var(--ink-dim)}

/* ── Field Ops: the pass readout. Reported material, but in body type -
   this is a sentence ("RISES SW, PEAKS NE 62°"), not a telemetry grid, so
   it skips the .data monospace Sky Watch's .tele uses. The sun-elevation
   and "nothing found" lines are printed by fieldops.js itself with class
   "tapenote n-hand" (matching notices.js's own hand line), which the
   .tapenote rule above already renders in the same voice as .hand. */
.fieldops{color:var(--ink);line-height:1.6;margin:1rem 0}
.fieldops p{margin:.4rem 0}
.fieldops .hi{color:var(--ink);font-weight:600}
.fieldops .dim{color:var(--ink-dim)}

/* ── the control row: catalogue picker, refresh, locate, zoom ── */
.ctlrow{display:flex;flex-wrap:wrap;align-items:end;gap:1rem 1.75rem;margin-top:1.25rem}

.picker,.faderwrap{display:flex;flex-direction:column;gap:.3rem}
.picker span,.faderwrap span{
  font-family:var(--f-data);font-size:var(--step--1);letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-dim);
}
.picker select{
  font-family:var(--f-data);font-size:var(--step--1);
  background:var(--panel);color:var(--ink);border:1px solid var(--edge);
  padding:.45rem .55rem;
}
/* --signal, matching cards.css's global a/button/summary focus rule - not
   --accent, which Task 1 deleted from tokens.css. This is the fix for the
   defect Task 4's reviewer carried in: all three focus-visible rules below
   computed to no outline at all, because var() of an undefined custom
   property resolves to nothing rather than erroring. */
.picker select:focus-visible{outline:2px solid var(--signal);outline-offset:2px}

.metalbtn{
  font-family:var(--f-data);font-size:var(--step--1);letter-spacing:.12em;
  text-transform:uppercase;background:var(--panel);color:var(--ink);
  border:1px solid var(--ink);padding:.5rem .9rem;cursor:pointer;
}
.metalbtn:hover{background:var(--void)}
.metalbtn:focus-visible{outline:2px solid var(--signal);outline-offset:3px}

/* A proper touch target, not a bare form control - wheel-zoom alone means
   no zoom at all on a phone, which is exactly the device this station is
   watched from. */
.faderwrap input[type="range"]{
  -webkit-appearance:none;appearance:none;
  width:min(160px,42vw);height:34px;margin:0;
  background:var(--panel);border:1px solid var(--edge);
  cursor:pointer;touch-action:pan-y;
}
.faderwrap input[type="range"]::-webkit-slider-runnable-track{height:34px;background:transparent}
.faderwrap input[type="range"]::-webkit-slider-thumb{
  -webkit-appearance:none;appearance:none;
  width:26px;height:26px;margin-top:0;border-radius:3px;
  background:var(--ink);border:1px solid var(--ink);cursor:pointer;
}
.faderwrap input[type="range"]::-moz-range-track{height:34px;background:transparent;border:none}
.faderwrap input[type="range"]::-moz-range-thumb{
  width:26px;height:26px;border-radius:3px;
  background:var(--ink);border:1px solid var(--ink);cursor:pointer;
}
.faderwrap input[type="range"]:focus-visible{outline:2px solid var(--signal);outline-offset:3px}

@media (max-width:700px){
  .scopewrap{max-width:100%}
  #scope{width:min(280px,80vw)}
}

/* ── Case File: the report controls (Furniture) ──
   Reimplements rack.css's .report/.detents/.pad on the semantic aliases -
   the rack page still uses the metal originals, but this page never links
   rack.css, so those rules are invisible here. */
.report{display:flex;gap:clamp(1rem,3vw,2rem);flex-wrap:wrap;align-items:flex-start;margin:1.25rem 0}
.report fieldset{border:none;margin:0;padding:0}
.report legend{
  font-family:var(--f-data);font-size:var(--step--1);letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-dim);padding:0 0 .5rem;
}
.detents{display:flex;gap:.4rem;flex-wrap:wrap}

/* The pad is square on purpose - eight compass points around straight up.
   It reads as a keypad and stays tappable on a phone. */
.pad{display:grid;grid-template-columns:repeat(3,1fr);gap:.3rem;max-width:13rem}
.pad .metalbtn{
  padding:.6rem .2rem;letter-spacing:.1em;aspect-ratio:1;
  display:flex;align-items:center;justify-content:center;text-align:center;
}

/* Selection is a lit key, not a colour swap on the label: --signal rings
   the selected key's border instead of repainting the text, so the
   already-measured "text inside a card" pair (ink on panel) never changes
   underneath it, and no new contrast row is needed for the ring itself -
   --signal on --panel is the same pair already measured as "accent text in
   a card". */
.report .metalbtn[aria-checked="true"]{
  border-color:var(--signal);
  box-shadow:inset 0 0 0 1px var(--signal);
}
#u3-noidea{margin-top:.4rem;width:100%;max-width:13rem}

@media (max-width:700px){
  .report{gap:1rem}
}

/* ── Case File: the file, printed under the verdict (Reported) ──
   Mirrors glass.css's .file/.row rules on the newspaper's own aliases: the
   verdict is Reported material sitting inside the console card like the
   rest of .tele, never a card of its own.

   Long catalogue names must not push the page sideways at 390px. They now
   WRAP rather than scroll, and that change is a bug fix, not a preference.
   This block used to carry overflow-x:auto, which makes it a scroll
   container - and CSS then forces overflow-y from visible to auto too,
   because the two axes cannot disagree about being clipped. Its last child
   is .tapenote, which is handwriting and therefore rotated, and a rotated
   box contributes its transformed corners to the scrollable overflow
   region: 1.9px of it at 1440px wide. Chromium makes any scrollable
   container keyboard-focusable, so this non-interactive div took a tab stop
   on the way to FILE IT and showed the browser's default focus ring instead
   of the site's --signal one. Width-dependent, too - at 390px the numbers
   rounded to equal and the stop vanished, which is what an accidental
   feature looks like.

   overflow-wrap:anywhere keeps the original promise (nothing pushes the
   page sideways) without the scroll container: it is the same tool
   .sight-what and .above-place already use for the same problem, and for a
   civilian reader a wrapped designation beats one hidden off the edge of a
   row nobody will think to drag.

   display:flow-root is doing a second, quieter job, and removing it moves
   the page. overflow-x:auto was also establishing a block formatting
   context, which contained the last child's 4px bottom margin. Dropping the
   overflow alone let that margin collapse out of the box and pulled the
   FILE IT row 4px up - measured, 19.3px to 15.3px between the handwriting
   and the button. flow-root restores exactly that containment and nothing
   else: it is a BFC without a scroll container, so the box is the same
   height it always was and still takes no tab stop. */
.file{
  margin-top:.9rem;border-top:1px solid var(--edge);padding-top:.6rem;
  display:flow-root;overflow-wrap:anywhere;
}
.file .row{
  display:flex;gap:clamp(.5rem,2vw,1.1rem);flex-wrap:wrap;
  line-height:1.5;margin:.25rem 0;
}
.file .row .when{color:var(--ink-dim);white-space:nowrap}
.file .row .way{color:var(--ink-dim);min-width:3.5em}
.file .row .what{color:var(--ink)}
.file .row .scope{color:var(--signal)}

/* ── Front Page: the founding story ──
   The lead article itself (.kicker/.standfirst/.hand) and the box
   (.boxed/.cutline) are already styled generically in page.css; this is
   only the digest's own spacing. The section teasers live in hero.css, not
   here - hero.css is the one sheet that loads only on the page that has any
   .teasers to style.

   The boxed scope figure that used to be specified here is gone: the Live
   Sky Tracker (tracker.css) superseded it on the front page, and two
   all-sky domes on one page is one too many. Its three rules went with it -
   .frontscope no longer exists in any markup, and the front page's #scope
   is now the tracker's dome, which tracker.css styles. Sky Watch's own
   #scope rules above are untouched, and that page never links tracker.css. */
#founding{margin:1.5rem 0}

/* ── About: the colophon's label/value rows ──
   The one piece of genuinely new layout the dedication needed - everything
   else on the page (the boxed panel, its heading, its closing note, the
   corrections column, the personals line) is .boxed/.sechead/.prose/
   .cutline/.hand, reused exactly as they already were. Label style matches
   .picker span elsewhere on the page: mono, small, letter-spaced, dim. */
.indicia{margin:.9rem 0 0}
.indicia>div{display:flex;flex-wrap:wrap;gap:.4rem 1rem;margin:.4rem 0}
.indicia dt{
  flex:0 0 auto;min-width:9.5rem;
  font-family:var(--f-data);font-size:var(--step--1);letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-dim);
}
.indicia dd{margin:0;flex:1 1 14rem;color:var(--ink)}
