/* CurveNumber shared interface layer.

   One place for the things every screen must do the same way: the skip link,
   focus, touch targets, links, bare buttons, wide tables, the side-branch
   shell, notices and the phone layout of the map. It loads after style.css
   and workspace.css and uses only their tokens, so a colour or a size is
   still decided in exactly one place (the :root block in style.css). */

/* ---------- skip link and screen-reader text ---------- */
.skip-link {
  position: absolute; left: .5rem; top: -4rem; z-index: 1000;
  background: var(--accent); color: var(--surface); padding: .7rem 1rem;
  font: 600 14px/1 var(--sans); border-radius: 3px; text-decoration: none;
}
.skip-link:focus { top: .5rem; outline: var(--focus-ring); outline-offset: 2px; }
.sr-only {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
main:focus { outline: none; }
/* Headings that receive focus so a screen reader starts reading there. */
h1[tabindex="-1"]:focus, h2[tabindex="-1"]:focus, h3[tabindex="-1"]:focus, .delta[tabindex="-1"]:focus { outline: none; }
[tabindex="-1"]:focus:not(:focus-visible) { outline: none; }

/* ---------- one focus ring ---------- */
a:focus-visible, button:focus-visible, summary:focus-visible, [role="button"]:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: var(--focus-ring); outline-offset: 2px;
}
/* The map canvas is a focus stop (MapLibre makes it one for keyboard panning)
   and it used to have `outline: none`, so a keyboard user landed on it and
   could not see where they were. */
#map canvas:focus-visible, #map:focus-within canvas:focus-visible {
  outline: var(--focus-ring); outline-offset: -3px;
}

/* ---------- base elements, so nothing falls back to browser defaults ---------- */
/* Zero specificity, so a component that colours its own links (the brand,
   the nav) keeps its colour, visited or not. */
:where(a) { color: var(--accent); text-underline-offset: 2px; }
:where(a:visited) { color: var(--accent); }
:where(a:hover) { text-decoration-thickness: 2px; }
/* A button with no class used to render as the browser's grey outset block in
   Arial, on both themes. It now looks like the ghost button. */
/* :where() keeps this at the specificity of a bare `button`, so every
   component rule that styles its own buttons (.map-basemap button,
   .admin-menu button, ...) still wins. */
:where(main, dialog) button:where(:not([class])) {
  font-family: var(--sans); font-size: 13px; padding: .45rem .9rem; border-radius: 2px;
  background: transparent; color: var(--ink-mid); border: 1px solid var(--line-strong);
  cursor: pointer;
}
:where(main, dialog) button:where(:not([class])):hover { border-color: var(--accent); color: var(--accent); }
select { color-scheme: light dark; }

/* Provenance chips set side by side read as one word ("C/DUNRESOLVED
   COMPUTED"). A gap keeps them two. */
.origin + .origin, .origin + .flagged, .flagged + .origin { margin-left: .35rem; }

/* Workflow chips were light-theme hex values; they follow the tokens now. */
.workspace-steps .step-status { background: var(--sunk); color: var(--ink-mid); }
.workspace-steps [data-status="saved"] .step-status { background: var(--accent-soft); color: var(--accent); }
.workspace-steps [data-status="warning"] .step-status { background: var(--ochre-soft); color: var(--ochre); }
.workspace-steps button[aria-current=step] .step-status { background: var(--surface); color: var(--accent); }

/* ---------- wide tables: scroll with a visible cue ---------- */
.scroll {
  /* Positioned, so a visually hidden label inside a wide table is clipped by
     the scroll box instead of widening the page on a phone. */
  position: relative;
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  background:
    linear-gradient(to right, var(--surface) 30%, transparent) left center / 24px 100% no-repeat local,
    linear-gradient(to left, var(--surface) 30%, transparent) right center / 24px 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, rgba(0,0,0,.18), transparent) left center / 10px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, rgba(0,0,0,.18), transparent) right center / 10px 100% no-repeat scroll;
}

/* ---------- touch targets ----------
   44 px is the smallest thing a finger is asked to hit. On a touch screen
   every control grows to it; on a desktop the dense layout stays. */
@media (pointer: coarse) {
  button, .tool, nav button, button.small, button.ghost, button.primary,
  input:not([type="checkbox"]):not([type="radio"]), select, summary,
  .geo-btn, .map-basemap button, .lg-x, .geo-clear, .map-alert-x {
    min-height: var(--touch-target);
  }
  button.small, .tool.minor { font-size: 13px; padding-left: .7rem; padding-right: .7rem; }
  .lg-x, .map-alert-x { min-width: var(--touch-target); }
  input[type="checkbox"], input[type="radio"] { width: 22px; height: 22px; }
  .maplibregl-ctrl-group button { width: var(--touch-target) !important; height: var(--touch-target) !important; }
  label { font-size: 12px; }
}

/* ---------- notices: one toast, one error presenter ---------- */
.cn-toasts { position: fixed; left: 50%; bottom: 1rem; transform: translateX(-50%); z-index: 900;
             display: flex; flex-direction: column; gap: .5rem; width: min(560px, calc(100vw - 2rem)); }
.cn-toast {
  display: flex; align-items: center; gap: .75rem; padding: .7rem .9rem;
  background: var(--ink); color: var(--surface); border-radius: 4px; box-shadow: var(--shadow);
  font-size: 13.5px; line-height: 1.45;
}
.cn-toast span { flex: 1; }
.cn-toast button { background: transparent; color: var(--surface); border: 1px solid currentColor;
                   border-radius: 2px; padding: .35rem .7rem; cursor: pointer; font: 500 13px var(--sans); }
.err-ref { display: block; margin-top: .35rem; font-family: var(--mono); font-size: var(--fs-min);
           color: var(--ink-mid); }
.err-fields { margin: .4rem 0 0 1.1rem; padding: 0; }
.field-msg { display: block; color: var(--red); font-size: 12px; margin-top: .2rem; }
input[aria-invalid="true"] { border-color: var(--red); }

/* ---------- side branches ----------
   Every side analysis wears the same shell: a strip that says it is a side
   analysis, what main-path value it can change, and a way back. It ends in
   one primary "Use this result" (or "Done" where nothing flows back) and a
   secondary "Discard". */
.branch { border-left: 4px solid var(--accent-line); }
.branch-head {
  display: flex; align-items: center; flex-wrap: wrap; gap: .4rem .8rem;
  padding: .55rem 1rem; background: var(--accent-soft); border-bottom: 1px solid var(--line);
  font-size: 12.5px; color: var(--ink-mid);
}
.branch-eyebrow { font: 600 var(--fs-min)/1.3 var(--mono); letter-spacing: .1em; text-transform: uppercase;
                  color: var(--accent); }
.branch-changes { flex: 1; min-width: 12rem; }
.branch-foot { display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; padding: .75rem 1rem;
               border-top: 1px solid var(--line); }
.branch-foot .branch-note { flex: 1 1 14rem; font-size: 12px; color: var(--ink-mid); }
.branch-changed { animation: branch-flash 2.4s ease-out 1; box-shadow: 0 0 0 3px var(--accent); }
@keyframes branch-flash { 0% { background: var(--accent-soft); } 100% { background: inherit; } }
.side-branches { display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; margin: 1rem 0 1.25rem;
                 padding: .75rem 1rem; border: 1px dashed var(--accent-line); border-radius: 8px;
                 background: var(--surface); }
.side-branches > strong { font: 600 var(--fs-min)/1.3 var(--mono); letter-spacing: .1em; text-transform: uppercase;
                          color: var(--accent); margin-right: .25rem; }
.side-branches .branch-open { display: inline-flex; align-items: center; gap: .35rem; }
.stage-next { display: flex; justify-content: flex-end; gap: .6rem; margin: 1rem 0 1.5rem; }

/* ---------- view headings ---------- */
/* Every view has an h1 now. Views other than the workspace set it in the
   panel-title style they always had, so the page looks the same and a screen
   reader finds one top-level heading per view. */
.view-h1 { font-family: var(--serif); font-size: 1.35rem; font-weight: 600; margin: 0 0 .9rem; }

/* ---------- boundary import ---------- */
.import-dialog textarea { font-family: var(--mono); font-size: 12px; min-height: 9rem; }
.import-dialog .note { margin: .4rem 0; }
.import-dialog .import-file { margin-top: .6rem; }
.map-fallback { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
                padding: 1.5rem; text-align: center; background: var(--sunk); color: var(--ink-mid);
                font-size: 14px; line-height: 1.55; z-index: 4; }
.map-fallback div { max-width: 28rem; }
/* Outside the map, above the (hidden) drawing tools (round 2, Q4, RB-53). */
.map-fallback:not(.mapwrap .map-fallback) { position: static; inset: auto; margin: 0 0 .75rem; }

/* ---------- the map: badges never swallow a tap ---------- */
.map-overzoom, .map-readout, .map-legend .lg-head, .map-legend .lg-note { pointer-events: none; }
.tool.finish { font-weight: 600; color: var(--accent); border-color: var(--accent-line); }

/* ---------- the map on a phone ----------
   At 390 px the search box and the tool panel floated over the map and took
   about two thirds of it, and taps meant for the map landed on "Draw
   practice". Under 640 px the rail, the readout and the legend move into
   normal flow around the map, so every pixel of the map is map. */
@media (max-width: 640px) {
  .workspace-stage .mapwrap, .mapwrap {
    height: auto; min-height: 0; display: flex; flex-direction: column; overflow: visible;
  }
  .map-rail { position: static; width: auto; order: -1; margin-bottom: .5rem; }
  .map-rail .map-search, .map-rail .map-tools { box-shadow: none; -webkit-backdrop-filter: none;
                                                backdrop-filter: none; background: var(--surface); }
  .map-tools { display: flex; flex-wrap: wrap; gap: .35rem; }
  .map-tools .toolgroup { display: contents; }
  .map-tools .tool { flex: 1 1 30%; min-height: var(--touch-target); font-size: 13px; }
  .map-tools .map-hint { flex: 1 1 100%; }
  #map { position: relative; inset: auto; height: max(340px, 64dvh); flex: none; }
  .map-bl { position: static; width: auto; margin-top: .5rem; }
  .map-alert { left: auto; right: auto; top: auto; position: relative; order: -1; margin-bottom: .5rem; }
  .map-basemap { top: auto; bottom: auto; position: static; align-self: flex-start; margin-top: .5rem; }
  .map-overzoom { position: static; align-self: flex-start; margin-top: .35rem; max-width: none; }
  .map-panel > h2 .panel-sub { display: none; }
}
/* A tablet in portrait got a 350 px map. The height alone did nothing: the
   wrapper is a flex item with a zero basis (style.css), which overrides a
   height, so the basis is released here too (round 2, Q4, RB-53; measured
   350 px before and 708 px after at 820 x 1180). */
@media (min-width: 641px) and (max-width: 1100px) and (pointer: coarse) {
  .workspace-stage .mapwrap { height: max(480px, 60dvh); flex: none; }
}
.workspace-branch.branch { border-left: 0; }
.workspace-branch > .branch-head { border: 1px solid var(--accent-line); border-radius: 8px 8px 0 0; margin-bottom: 1rem; }
.branch-title { font: 600 1.05rem/1.3 var(--serif); margin: 0; color: var(--ink); flex-basis: 100%; }
.workspace-steps button[aria-current=step] { background: var(--accent); color: var(--surface); border-color: var(--accent); }

/* ---------- the header on a phone ----------
   Eight tabs at 44 px wrapped into four rows and took half the screen. On a
   phone they are one row that scrolls sideways, with the current tab kept in
   view by app.js. */
@media (max-width: 640px) {
  header nav { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
               scrollbar-width: none; padding-bottom: 2px; }
  header nav::-webkit-scrollbar { display: none; }
  header nav button { flex: none; }
  .acct { order: 5; width: 100%; }
}

/* ---------- workspace library ---------- */
/* Long names are clamped to two lines with an ellipsis; the full name is in
   the title and in the details dialog (C-68). */
.project-toggle strong, .site-open strong {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.workspace-pinned { margin-bottom: 12px; }
.workspace-pinned .eyebrow { margin: 0 0 6px; }
#project-list .empty { padding: 12px; }
#project-list .empty p { margin: 0 0 8px; }
.np-form > div { min-width: 100%; }
.np-form > div:last-child { min-width: 0; }

/* ---------- quick check and entry rows ---------- */
.qc-h { font: 600 14px/1.3 var(--sans); margin: 1rem 0 .5rem; }
.qc-h .note { font-weight: 400; margin-left: .35rem; }
.qc-form, .seg-form { margin-top: .5rem; }
.qc-form .row > div, .seg-form > div { min-width: 110px; }
.qc-warn:empty { display: none; }
.qc-warn { color: var(--ochre); }

/* The branch ending stays reachable on a long branch (round 2, RB-60: the
   practices branch is about 19,000 px tall on a phone). */
.workspace-branch > .branch-foot { position: sticky; bottom: 0; z-index: 2;
  background: var(--surface); border-top: 1px solid var(--line); }

/* ---------- a refusal: headline, what happened, what to do (round 2, Q4, RB-09) ---------- */
/* One card for every refusal: the headline first, one or two short lines,
   the action, and the developer text folded under "Details for reviewers". */
.refuse .rf-title { font: 600 15px/1.35 var(--sans); color: var(--ink); margin: .25rem 0 .15rem; }
.refuse .rf-r { font-size: 13px; line-height: 1.5; color: var(--ink); margin: .25rem 0 0; }
.refuse .rf-fix { font-size: 13px; line-height: 1.5; color: var(--ink); margin: .35rem 0 0; }
.refuse .rf-fix strong { font-weight: 600; }
.refuse .rf-more { margin-top: .5rem; }
.refuse .rf-more > summary { font-size: 12px; color: var(--ink-mid); cursor: pointer; min-height: 24px; }
.refuse .rf-more .rf-tax { margin: .35rem 0 0; display: flex; gap: .4rem; align-items: baseline; }
.refuse .rf-more .rf-w, .refuse .rf-more .rf-s { font-size: 12px; }
.wv-struct-line { font-size: 12.5px; color: var(--ink-mid); margin-top: .35rem; }
/* The request reference, which support needs, only on a server fault. */
.errbox .err-ref { display: block; margin-top: .3rem; font-size: var(--fs-min); color: var(--ink-mid); }
.errbox .rf-title, .warnbox .rf-title { font: 600 14px/1.35 var(--sans); display: block; margin-bottom: .2rem; }

/* ---------- Reference table footnotes (round 2, Q4, RB-80) ---------- */
.ref-fn { font-size: var(--fs-min); margin-left: 2px; }
.ref-fn a { text-decoration: none; padding: 0 2px; }
.ref-notes { margin: .6rem 0 0 1.2rem; padding: 0; }
.ref-notes li { margin: .2rem 0; }

/* ---------- accessibility leftovers (round 2, Q4, RB-62) ---------- */
/* A checkbox row is a finger's target as a whole, not the 22 px box. */
@media (pointer: coarse) {
  label:has(> input[type="checkbox"]), label:has(> input[type="radio"]) {
    min-height: var(--touch-target); display: inline-flex; align-items: center; gap: .5rem;
  }
}
/* 4.5:1 on the darker library panel, and on the selected History chip. */
#project-list .empty { color: var(--ink-mid); }
.hs-chip.on .hs-n { opacity: 1; }

/* ---------- wide tables on a phone (round 2, Q4, RB-46) ---------- */
/* A grid child may shrink below its content, so a wide table scrolls inside
   its own box instead of pushing the page wider than the screen. A `.row`
   child already has an explicit floor (style.css, 90 px); zero there let the
   `flex:0` button cells collapse onto each other (Account: Close this account
   lay over Sign out). */
.grid2 > *, .grid3 > * { min-width: 0; }
.scroll:focus-visible { outline: var(--focus-ring, 2px solid var(--accent)); outline-offset: 2px; }

/* ---------- one theme control (round 2, Q4, RB-69) ---------- */
/* The console loads this sheet and not style.css, so the glyph and the
   clipped state word are set here too: the console printed AUTO and DARK. */
#theme-toggle [data-theme-label] {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
#theme-toggle::before { content: "\25D0"; font-size: 12px; line-height: 1; letter-spacing: 0; }
html[data-theme="light"] #theme-toggle::before { content: "\25CB"; }
html[data-theme="dark"] #theme-toggle::before { content: "\25CF"; }

/* ---------- notices stay off the map on a phone (round 2, Q4, RB-75) ---------- */
@media (max-width: 640px) {
  .cn-toasts { top: .75rem; bottom: auto; }
}

/* ---------- the stage bar on a phone ----------
   Five stage cards in two columns took about 500 px above every stage, so
   Results opened with its answer a screen and a half down (round 4,
   R3-0353). Under 640 px the bar is one row that scrolls sideways, like the
   header, with the current stage kept in view by workspace.js. */
@media (max-width: 640px) {
  .workspace-steps { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none; gap: 6px; margin-bottom: 12px; padding-bottom: 10px; }
  .workspace-steps::-webkit-scrollbar { display: none; }
  .workspace-steps button { flex: 0 0 auto; min-width: 0; padding: 8px 10px; gap: 4px; }
  .workspace-steps button > span { white-space: nowrap; }
  .workspace-steps .step-status { white-space: nowrap; font-size: 11.5px; }
}

/* ---------- one destructive style (round 5, R5-0141, R5-0147) ----------
   The console's red outline is the product's one style for an act that
   removes something: the trigger is outlined in red, and the dialog's own
   go button is filled in red. Customer and console use the same class. */
button.danger, button.ghost.danger { background: transparent; color: var(--red); border: 1px solid var(--red); }
button.danger:hover:not(:disabled), button.ghost.danger:hover:not(:disabled) { background: var(--red-soft); color: var(--red); border-color: var(--red); }
button.primary.danger { background: var(--red); color: var(--surface); border-color: var(--red); }
button.primary.danger:hover:not(:disabled) { background: var(--red); color: var(--surface); filter: brightness(1.1); }
.cn-confirm h2 { margin-top: 0; }
.cn-confirm p { margin: 0 0 .6rem; line-height: 1.5; }

/* ---------- the Compute form (round 5, R5-0132) ----------
   One grid, labels at the top of every field, each hint under its own
   field at the field's width; a field whose hint is a sentence or more
   (the distribution, the unit hydrograph, a proposed Tc estimate) takes the
   whole row so the sentence reads as one. One column on a phone. */
.run-form { display: flex; flex-wrap: wrap; gap: .85rem 1rem; align-items: flex-start; margin-top: 1rem; }
.run-form .run-field { flex: 1 1 12rem; display: flex; flex-direction: column; min-width: 0; }
.run-form .run-field-tc { flex-basis: 21rem; }
.run-form .run-field > input, .run-form .run-field > select { width: 100%; box-sizing: border-box; }
.run-form .run-field > .note { margin: .3rem 0 0; font-size: 12.5px; line-height: 1.45; max-width: 72ch; }
.run-form .run-field > .note:empty { display: none; }
.run-form .run-field-wide, .run-form .run-actions,
.run-form .run-field:has(> .note:not(:empty)):not(.run-field-short) { flex-basis: 100%; }
.run-form .run-field-wide > input, .run-form .run-field-wide > select,
.run-form .run-field:has(> .note:not(:empty)):not(.run-field-short) > input { max-width: 27rem; }
.run-form .run-check label { display: inline-flex; align-items: center; gap: .5rem;
  text-transform: none; letter-spacing: 0; font: 400 13.5px/1.4 var(--sans); color: var(--ink); }
.run-form .run-actions { display: flex; gap: .6rem; align-items: center; }
@media (max-width: 640px) {
  .run-form .run-field { flex-basis: 100%; }
  .run-form .run-field-wide > input, .run-form .run-field-wide > select,
  .run-form .run-field:has(> .note:not(:empty)) > input { max-width: none; }
}

/* ---------- entry rows keep their line when a message appears (R5-0172) ---------- */
.qc-form .row, .seg-form.row { align-items: flex-start; }
.qc-form .row > div:last-child, .seg-form.row > div:last-child { align-self: flex-start; padding-top: 1.35rem; }
@media (pointer: coarse) { .qc-form .row > div:last-child, .seg-form.row > div:last-child { padding-top: 1.25rem; } }

/* ---------- the quick check printout (round 5, R5-0015, R5-0170) ---------- */
.qc-print { display: flex; flex-wrap: wrap; gap: .6rem 1rem; align-items: flex-end; margin: 0;
            padding: .85rem 1rem; border: 1px solid var(--line); border-radius: 6px; background: var(--sunk); }
.qc-print .qc-print-field { flex: 1 1 16rem; min-width: 0; }
.qc-print .qc-print-field input { width: 100%; }
.qc-print .note { flex: 1 1 100%; margin: 0; font-size: 12.5px; }

/* ---------- waivers filed ahead (round 5, R5-0022) ---------- */
.wv-ahead { margin-top: 1rem; padding-top: .9rem; border-top: 1px solid var(--line); }
.wv-ahead h3 { font: 600 14px/1.3 var(--sans); margin: 0 0 .35rem; }
.wv-ahead .wv-ahead-pick { display: flex; flex-wrap: wrap; gap: .6rem; align-items: flex-end; margin: .5rem 0; }
.wv-ahead .wv-ahead-pick > div { flex: 1 1 18rem; min-width: 0; }
.wv-ahead .wv-ahead-pick select { width: 100%; }
.run-form .run-check input[type="checkbox"] { width: auto; flex: none; margin: 0; }

/* ---------- the AI meter's figure follows its bar (round 5, R5-0158) ---------- */
.asst-an.warn { color: var(--ochre); }
.asst-an.bad { color: var(--red); }
.asst-allow-spent .asst-an.warn, .asst-allow-spent .asst-an.bad { color: var(--ink-soft); }
