/*
 * Se7en Error Checker.
 *
 * ⚠️ Dark Solarized, the suite's palette — see WebAppsToolBoxInfrastructure's
 *    site/assets/css/toolbox.css for the full table and the contrast rules.
 *    Copied rather than shared because this application deploys to its own
 *    docroot and must work offline with no cross-origin fetch.
 *
 * 🔴 TWO CONTRAST RULES, BOTH MEASURED, BOTH EASY TO GET WRONG:
 *    1. --base00 and --base01 NEVER carry text. 3.37:1 and 2.79:1 on the page
 *       background — both fail AA. They are rules and dividers.
 *    2. Body text is --base0 on --base03 (4.75:1) but --base1 on --base02
 *       (4.86:1). The token that passes on the page FAILS on a card.
 *
 * ⚠️ The accent is YELLOW — Poseidon's own livery, chosen 2026-09-14. See the
 *    box beside --accent for why, and for the DiveSites clash it creates. No
 *    Solarized accent reaches 4.5:1 as text on either dark ground, so accents
 *    carry colour, never legibility.
 */

:root {
  --base03: #002b36;
  --base02: #073642;
  --base01: #586e75;
  --base00: #657b83;
  --base0:  #839496;
  --base1:  #93a1a1;
  --base2:  #eee8d5;
  --yellow: #b58900;
  --red:    #dc322f;

  /*
   * ┌──────────────────────────────────────────────────────────────────────┐
   * │ 🔴 YELLOW, NOT ORANGE — AND IT IS A PRODUCT DECISION.                │
   * │                                                                      │
   * │ Yellow on black is Poseidon's own livery, so a diver recognises what │
   * │ this tool is for before reading a word. Chosen 2026-09-14.           │
   * │                                                                      │
   * │ ✅ THE SUITE'S TABLE NOW AGREES — swapped 2026-09-14 in the          │
   * │    infrastructure repo's CLAUDE.md and toolbox.css. Two products     │
   * │    cannot share an accent and the palette is full, so DiveSites took │
   * │    orange. That half is a consequence, not a preference.             │
   * │                                                                      │
   * │ 🔴 THIS FILE IS A DUPLICATE OF THE SUITE PALETTE, ON PURPOSE — the   │
   * │    app must work offline with no cross-origin fetch. So a change to  │
   * │    toolbox.css does NOT reach here, and a change here does not reach │
   * │    the product page. CHANGE BOTH.                                    │
   * │                                                                      │
   * │ ⚠️ Colour alone implies no affiliation, and the disclaimer is on     │
   * │    every view — but it is worth knowing this leans on their visual   │
   * │    identity deliberately rather than by accident.                     │
   * └──────────────────────────────────────────────────────────────────────┘
   */
  --accent: var(--yellow);
}

* { box-sizing: border-box; }

/*
 * ⚠️ NO SIDE PADDING ON body — <main> carries it, so the footer menu after it
 *    can run edge to edge like WebAppsToolBox.com's nav (2026-10-02). A column
 *    flexbox puts that band on the bottom of the screen when a page is short.
 */
body {
  margin: 0;
  padding: 0;                         /* the banner sits flush at the top; <main> spaces itself */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--base03);
  color: var(--base0);
  font: 16px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

main {
  flex: 1 0 auto;
  width: 100%;
  max-width: calc(42rem + 2rem);      /* the 42rem column, plus its padding */
  margin: 0 auto;
  padding: 1.5rem 1rem 0;
}

h1 {
  color: var(--base2);
  font-size: 1.6rem;
  margin: 0 0 .25rem;
  border-bottom: 3px solid var(--accent);
  padding-bottom: .5rem;
}

h2 { color: var(--base1); font-size: 1.15rem; margin: 0 0 .5rem; }

.lede { color: var(--base1); margin: 0 0 1.5rem; }

/* --- the pickers --------------------------------------------------------- */

.picker { margin: 0 0 1.5rem; }

label {
  display: block;
  color: var(--base1);
  font-size: .85rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  margin-bottom: .35rem;
}

select {
  width: 100%;
  padding: .7rem;
  background: var(--base02);
  color: var(--base1);          /* 🔴 base1 on base02, not base0 — see the header */
  border: 1px solid var(--base01);
  border-radius: 4px;
  font-size: 1rem;
}

select:focus { outline: 2px solid var(--accent); outline-offset: 2px; }

button {
  margin-top: .6rem;
  padding: .6rem 1.1rem;
  background: var(--base02);
  color: var(--base2);
  border: 1px solid var(--base01);
  border-radius: 4px;
  font-size: 1rem;
  cursor: pointer;
}

button:hover { border-color: var(--accent); }

/*
 * ⚠️ Hidden ONLY when scripting is available and has taken over. Without JS the
 *    button is the only way to submit, so it must never be hidden by default.
 */
body.js-ready .picker button { display: none; }

/* --- results -------------------------------------------------------------- */

.step {
  background: var(--base02);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
  padding: 1rem 1.1rem;
  margin: 0 0 1.5rem;
  color: var(--base1);
}

.meta { color: var(--base0); font-size: .9rem; margin: 0 0 .75rem; }

/*
 * The test heading, with the units that run it top-right (Paul, 2026-09-25):
 *
 *   Test 26                          [MkVI] [Se7en] [Se7en+]
 *   Oxygen Calibration Solenoid.
 */
.test-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: .75rem;
  margin: 0 0 .6rem;
}

.test-head h2 { margin: 0; }

/*
 * The tag column, top-right: the units, then the time limit beneath them —
 *
 *   [MkVI] [Se7en] [Se7en+]
 *             [120 seconds]
 */
.test-head__tags {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: .3rem;
  flex: none;
  max-width: 55%;
  margin-top: .15rem;
}

.units {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: .3rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* One look for every tag — a unit, or the time limit. */
.units li,
.duration {
  font-size: .72rem;
  line-height: 1;
  letter-spacing: .02em;
  color: var(--base2);          /* on base03 inside the card — plenty of contrast */
  background: var(--base03);
  border: 1px solid var(--base01);
  border-radius: 3px;
  padding: .3rem .45rem;
  white-space: nowrap;
}

.duration { margin: 0; font-variant-numeric: tabular-nums; }

/* Read aloud, never seen — the tag shows "120 seconds"; a screen reader hears "Up to 120 seconds allowed". */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/*
 * ⚠️ THE DESCRIPTION IS ITS OWN TOGGLE — two lines while closed, whole when
 *    open (Paul, 2026-09-25: "default to unexpanded"). No marker: the ellipsis
 *    says there is more, and tapping the text shows it.
 */
.about { margin: 0 0 .6rem; }

.about summary {
  cursor: pointer;
  list-style: none;
  color: var(--base1);
  font-size: .95rem;
}

.about summary::-webkit-details-marker { display: none; }

.about:not([open]) summary {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}

/*
 * An error: the manual's label, big — then Poseidon's code-sheet sentence,
 * smaller, beneath it (TEXT-REVIEW.md, decision 2 → B).
 */
.meaning { color: var(--base2); font-size: 1.05rem; margin: 0 0 1rem; }
.meaning:has(+ .detail) { margin-bottom: .2rem; }
.detail { color: var(--base1); font-size: .88rem; margin: 0 0 1rem; }   /* base1 on base02 */

/* The result heading reuses .test-head, so its h2 keeps the old spacing. */
.result .test-head { margin-bottom: .5rem; }

.solutions { margin: 0; padding-left: 1.4rem; }
.solutions li { margin-bottom: .6rem; color: var(--base1); }

/*
 * 🔴 THE GAP STATE IS RED, AND IT IS THE ONLY RED IN THE APP.
 *    Red means "something is wrong here" — in this case, wrong with OUR data,
 *    not with the unit. Saying so plainly beats a blank the reader would take
 *    for a rendering fault.
 */
.gap {
  color: var(--red);
  font-style: italic;
}

/* --- the banner ------------------------------------------------------------- */

/*
 * ┌──────────────────────────────────────────────────────────────────────────┐
 * │ THE BANNER, STYLED LIKE WebAppsToolBox.com's TOP NAV — Paul, 2026-10-05. │
 * │ Brand left, Restart · Tell us · WebAppsToolBox right; sticky, 48px,      │
 * │ full width, outside <main>. Copied from toolbox.css .nav / .nav__bar /   │
 * │ .nav__brand / .nav__link, not linked — the app must work offline.        │
 * │ 🔴 CHANGE BOTH, as the palette and the footer menu.                      │
 * │                                                                          │
 * │ ⚠️ No hamburger, unlike the site: three short links fit a 320px phone,   │
 * │    once the brand drops to the short name.                               │
 * └──────────────────────────────────────────────────────────────────────────┘
 */
.appbar {
  flex: none;
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(7, 54, 66, 0.72);                  /* = toolbox.css .nav */
  border-bottom: 1px solid rgba(88, 110, 117, 0.35);
  padding-top: env(safe-area-inset-top, 0px);         /* the notch, in standalone mode */
}

@supports (backdrop-filter: blur(20px)) or (-webkit-backdrop-filter: blur(20px)) {
  .appbar {
    background: rgba(7, 54, 66, 0.62);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    backdrop-filter: saturate(180%) blur(20px);
  }
}

.appbar__bar {
  height: 48px;                                       /* = --nav-h */
  max-width: 1180px;                                  /* = --wrap-wide */
  margin: 0 auto;
  padding: 0 22px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.appbar__brand {
  display: flex;
  align-items: center;
  gap: .5rem;
  min-width: 0;
  color: var(--base2);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.01em;
  white-space: nowrap;
  text-decoration: none;
}
.appbar__brand:hover { color: #fdf6e3; text-decoration: none; }
.appbar__brand svg { width: 20px; height: 20px; flex: none; color: var(--accent); }
.appbar__short { display: none; }

.appbar__links {
  display: flex;
  align-items: center;
  gap: clamp(.75rem, 3vw, 2.4rem);                   /* = .nav__links, floor lowered */
  list-style: none;
  margin: 0;
  padding: 0;
}
.appbar__links li { display: flex; }    /* centres a logo'd link with the plain ones */

.appbar__link {
  font-size: 12px;
  letter-spacing: .01em;
  color: var(--base1);
  text-decoration: none;
  white-space: nowrap;
  transition: color .2s ease;
}
.appbar__link:hover { color: var(--base2); text-decoration: none; }

/* The WebAppsToolBox link carries the suite's logo, as the site's own brand does. */
.appbar__link--suite { display: inline-flex; align-items: center; gap: .35rem; }
.appbar__link--suite svg { width: 16px; height: 16px; flex: none; }
.appbar__link[aria-current="page"] { color: #fdf6e3; }
.appbar__brand:focus-visible,
.appbar__link:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* The full name needs ~560px beside the three links; below that, the short name. */
@media (max-width: 599px) {
  .appbar__bar { padding: 0 1rem; }
  .appbar__full { display: none; }
  .appbar__short { display: inline; }
}

@media (max-width: 389px) {    /* measured: 360 and 375 clipped the brand at 359 */
  .appbar__bar { padding: 0 .6rem; gap: .75rem; }
  .appbar__brand { font-size: 14px; flex: none; }
  /* ⚠️ The WATB logo on the suite link costs ~20px a 320px phone does not
        have, so the app's own icon gives way — the name still says what it is. */
  .appbar__brand svg { display: none; }
  .appbar__links { gap: .55rem; }
  .appbar__link { font-size: 11px; letter-spacing: 0; }
}

/* --- the footer menu (the disclaimer lives here) ---------------------------- */

/*
 * ┌──────────────────────────────────────────────────────────────────────────┐
 * │ A MENU, STYLED LIKE WebAppsToolBox.com's TOP NAV — Paul, 2026-09-25,     │
 * │ and MATCHED IN SHAPE 2026-10-02: a full-width 48px band, square edges,  │
 * │ outside <main>. It was a rounded card inside the 42rem column, which    │
 * │ read as content rather than as the site's menu.                          │
 * │                                                                          │
 * │ Copied from toolbox.css .nav / .nav__link, not linked: this app deploys  │
 * │ to its own docroot and must work offline. Same restraint: a translucent │
 * │ base02 band, small centred items with no dividers, base1 at rest, base2  │
 * │ on hover, base3 for the page you are on. 🔴 CHANGE BOTH, as the palette. │
 * │                                                                          │
 * │ 🔴 "Independent and unofficial" is its first item, on every view — the   │
 * │    bar alone carries the disclaimer now (see CheckerController).         │
 * └──────────────────────────────────────────────────────────────────────────┘
 *
 * ⚠️ Pushed well clear of the content with margin, not empty elements — some
 *    screen readers announce those as blank content.
 */
.disclaimer {
  flex: none;
  margin-top: 3rem;
  background: rgba(7, 54, 66, 0.72);                  /* = toolbox.css .nav */
  border-top: 1px solid rgba(88, 110, 117, 0.35);     /* = .nav's border-bottom */
}

/*
 * 🔴 ONE ROW, ALWAYS (Paul, 2026-09-25) — hence one-word labels. Five of them
 *    at 12px fit a 360px phone with room to spare; the gap shrinks before
 *    anything wraps, and nowrap means it never does.
 */
.footer-links ul {
  display: flex;
  flex-wrap: nowrap;
  justify-content: center;
  align-items: center;
  gap: clamp(.45rem, 2.5vw, 2.4rem);                /* = toolbox.css .nav__links, floor lowered */
  list-style: none;
  margin: 0 auto;
  max-width: 1180px;                                  /* = --wrap-wide */
  /* 48px = --nav-h, PLUS the iPhone home bar — box-sizing would otherwise eat it */
  height: calc(48px + env(safe-area-inset-bottom, 0px));
  padding: 0 .5rem env(safe-area-inset-bottom, 0px);
}

.footer-links__link {
  font-size: 12px;
  letter-spacing: .01em;
  color: var(--base1);          /* base1 on base02 — 4.86:1, see the header */
  text-decoration: none;
  white-space: nowrap;
  transition: color .2s ease;
}

.footer-links__link:hover { color: var(--base2); text-decoration: none; }
.footer-links__link[aria-current="page"] { color: #fdf6e3; }   /* --base3, as the site */
.footer-links__link:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/*
 * ⚠️ FIVE ITEMS since 2026-10-05 ("Tell us" moved to the banner), so these steps
 *    now have slack; kept rather than re-measured, because they cost nothing.
 * ⚠️ SIX ITEMS ON ONE ROW, MEASURED — not guessed. At 12px the labels need ~300px;
 *    a 375px phone gives ~335. So below 390px the text steps down, and again
 *    below 340px (the 320px iPhone SE). Checked in headless Chrome at 320, 360,
 *    375, 390, 414 and 430 wide, 2026-09-25 — re-measure if a label changes.
 * 🔴 AFTER the rules above, not before: same specificity, so the later one wins.
 *    It sat above them at first and silently did nothing.
 */
@media (max-width: 389px) {
  .footer-links ul { gap: .4rem; }
  .footer-links__link { font-size: 11px; letter-spacing: 0; }
}

@media (max-width: 339px) {
  .footer-links ul { gap: .3rem; padding-left: .3rem; padding-right: .3rem; }
  .footer-links__link { font-size: 10px; }
}

@media (max-width: 480px) {
  main { padding: 1rem .75rem 0; }
  h1 { font-size: 1.35rem; }
}

/*
 * 🔴 THE UNKNOWN STATE IS NOT AN ERROR PAGE.
 *
 * A reserved test number that a firmware update has started using is a REPORT,
 * not a fault — the diver is telling us our data is out of date. So it reads as
 * a neutral invitation — base1 — rather than red, which is reserved for "our
 * data is wrong".
 */
.unknown { border-left-color: var(--base1); }
.unknown h2 { color: var(--base2); }

.report {
  display: inline-block;
  margin: .4rem 0;
  padding: .6rem 1.1rem;
  background: var(--accent);
  /*
   * 🔴 DARK TEXT ON YELLOW, NOT WHITE. Measured: white on #b58900 is about
   *    3.4:1 and FAILS AA; the page background on it is about 7.4:1 and
   *    passes comfortably. The old white was correct on orange (~4.6:1) and
   *    would have quietly become unreadable with the accent change.
   */
  color: var(--base03);
  border-radius: 4px;
  text-decoration: none;
  font-weight: 600;
}

.report:hover { text-decoration: underline; }


/* --- the first-launch acknowledgement ------------------------------------- */
/*
 * 🔴 [hidden] must actually hide. `display:flex` below would otherwise win over
 *    the attribute, and the dialog would be visible to everyone including
 *    people with scripting off — who could not dismiss it.
 */
.ack[hidden] { display: none; }

.ack {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background: rgba(0, 43, 54, .92);
  z-index: 200;                       /* above the sticky banner (100) — it must cover everything */
}

.ack__box {
  max-width: 30rem;
  background: var(--base02);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
  padding: 1.5rem;
  color: var(--base1);
}

.ack__box h2 { color: var(--base2); margin-top: 0; }
.ack__box p { color: var(--base1); }
.ack__box strong { color: var(--base2); }

/* ✅ Free now, always will be — said plainly, where it is read. */
.ack__free {
  color: var(--base2);
  font-weight: 600;
  border-top: 1px solid var(--base01);
  padding-top: .9rem;
}

.ack__box button { width: 100%; margin-top: .5rem; }
.ack__note { font-size: .8rem; color: var(--base0); margin-bottom: 0; }

/* --- a test with only one possible code ----------------------------------- */
/*
 * ⚠️ Stated, not offered. 15 of 43 tests can raise exactly one error, and a
 *    dropdown with one option is a question whose answer is already known.
 */
.only { margin: 0 0 .25rem; color: var(--base2); }

.only__label {
  display: block;
  color: var(--base1);
  font-size: .85rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  margin-bottom: .35rem;
}

.only strong { color: var(--base2); font-size: 1.1rem; }

/* One step reads as a sentence; "1." would imply a second that never comes. */
.single { color: var(--base1); margin: 0; }

/* --- provenance: Poseidon's documents are the source ------------------------ */
/*
 * 🔴 Every departure is boxed on the answer it touches (.departure). The full
 *    lists are the footer pages (.info). The per-test "Source: … p." line was
 *    removed 2026-09-25 — the citation lives on in sources.json.
 */
.info a { color: var(--base2); }

/*
 * ⚠️ A DEPARTURE FROM POSEIDON IS NEVER QUIET. Boxed, labelled, inside the
 *    result it touches. Not red — red means OUR data is missing something; this
 *    is a deliberate, sourced difference. The yellow rule marks it; base2 makes
 *    the label legible (no accent passes AA as text).
 */
.departure {
  margin: 1rem 0 0;
  padding: .6rem .8rem;
  background: var(--base03);
  border: 1px solid var(--base01);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
}

.departure p { color: var(--base1); margin: 0 0 .4rem; font-size: .92rem; }
.departure .meta { color: var(--base0); margin: 0; font-size: .85rem; }  /* base0 on base03: 4.75:1 */

/* Two classes, to outrank `.departure p` above. */
.departure .departure__label {
  color: var(--base2);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .05em;
  font-size: .78rem;
}

/* The four footer pages — ?page=… */
.back { margin: 0 0 1.5rem; font-size: .9rem; }
.back a { color: var(--base1); }

.info h2 { color: var(--base2); }
.info h3 { color: var(--base2); font-size: 1rem; margin: 1.3rem 0 .3rem; }
.info p, .info li { color: var(--base1); }   /* base1 on base03 */
.info strong { color: var(--base2); }
.info .sources { padding-left: 1.2rem; }
.info .sources li { margin-bottom: .6rem; }
.info .meta { font-size: .85rem; color: var(--base0); }

/* --- "seen something we don't cover?" — ?page=feedback ---------------------- */

.report-form label { margin-top: .8rem; }

.report-form input,
.report-form textarea {
  width: 100%;
  padding: .6rem;
  background: var(--base02);
  color: var(--base1);          /* 🔴 base1 on base02 — as select */
  border: 1px solid var(--base01);
  border-radius: 4px;
  font: inherit;
}

.report-form input:focus,
.report-form textarea:focus { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The prepared email, shown as it will be sent — line breaks and all. */
.report-preview {
  white-space: pre-wrap;
  font-size: .85rem;
  color: var(--base1);
  background: var(--base03);
  padding: .6rem .8rem;
  border-radius: 4px;
}

/* --- v2: My units, This happened to me, history (2026-10-05) ---------------- */

/*
 * ┌──────────────────────────────────────────────────────────────────────────┐
 * │ The same tokens as everything above — no new colour. Forms copy select / │
 * │ button; cards are .step.                                                 │
 * │                                                                          │
 * │ 🔴 TEXT INSIDE A CARD IS --base1, NEVER --base0: base0 on base02 fails   │
 * │    AA (see the header). .meta is base0 because it was written for the    │
 * │    page; inside v2 cards it is lifted to base1.                          │
 * └──────────────────────────────────────────────────────────────────────────┘
 */

/*
 * 🔴 A DEFAULT LINK COLOUR. There was none — only .back a — so any other link
 *    fell back to the browser's #00e, unreadable on base02 (found in the v2
 *    screenshots, 2026-10-05; v1's plain links had it too). Lowest specificity,
 *    so every styled link above keeps its own. Underlined, so not colour alone.
 */
a { color: var(--base2); }
a:hover { color: #fdf6e3; }

.logbook-strip {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem 1.4rem;
  margin: -.75rem 0 1.5rem;
  font-size: .95rem;
}
.logbook-strip--out { display: block; color: var(--base0); }

a.button {
  display: inline-block;
  padding: .6rem 1.1rem;
  background: var(--base02);
  color: var(--base2);
  border: 1px solid var(--base01);
  border-radius: 4px;
  text-decoration: none;
}
a.button:hover { border-color: var(--accent); text-decoration: none; }

/* The result's "This happened to me" — a button, not a card. */
.step.log-this { background: none; border: 0; padding: 0; }

.v2form input[type="text"],
.v2form input[type="date"],
.v2form input[type="datetime-local"],
.v2form textarea {
  width: 100%;
  padding: .7rem;
  background: var(--base03);
  color: var(--base1);
  border: 1px solid var(--base01);
  border-radius: 4px;
  font: inherit;
}
.v2form select { margin-bottom: .2rem; }
.v2form label { margin-top: .9rem; }
.v2form label:first-of-type { margin-top: 0; }
.v2form input:focus,
.v2form textarea:focus { outline: 2px solid var(--accent); outline-offset: 2px; }
.v2form .meta,
.unit-list .meta,
.entry .meta { color: var(--base1); margin: .3rem 0 0; font-size: .85rem; }

.v2form fieldset { border: 0; margin: .9rem 0 0; padding: 0; }
.v2form legend {
  color: var(--base1);
  font-size: .85rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  margin-bottom: .35rem;
  padding: 0;
}
/* A radio is a label you tap — large, because this is used on a boat. */
.v2form .choice {
  display: flex;
  align-items: center;
  gap: .6rem;
  margin: 0 0 .3rem;
  padding: .55rem .7rem;
  border: 1px solid var(--base01);
  border-radius: 4px;
  text-transform: none;
  letter-spacing: 0;
  font-size: 1rem;
  color: var(--base1);
  cursor: pointer;
}
.v2form .choice:has(input:checked) { border-color: var(--accent); color: var(--base2); }

.v2form--inline { display: flex; flex-wrap: wrap; align-items: end; gap: .5rem .75rem; margin: 0 0 1.5rem; }
.v2form--inline label { margin: 0; flex-basis: 100%; }
.v2form--inline select,
.v2form--inline input { flex: 1 1 10rem; width: auto; }
.v2form--inline button { margin-top: 0; }
.v2form--inline .meta { flex-basis: 100%; }

.notice {
  border-left: 3px solid var(--accent);
  background: var(--base02);
  color: var(--base2);
  padding: .6rem .9rem;
  border-radius: 4px;
  margin: 0 0 1.5rem;
}
/* Red means "something is wrong" here — the one other place it is used. */
.notice--error { border-left-color: var(--red); }

.unit-list { list-style: none; margin: 0; padding: 0; }
.unit-list li { padding: .6rem 0; border-top: 1px solid rgba(88, 110, 117, .35); }
.unit-list li:first-child { border-top: 0; padding-top: 0; }
.unit-list a { font-size: 1.05rem; }
.unit-list .meta { display: block; }

h2.sub { margin-top: 1.4rem; }

.badge {
  display: inline-block;
  margin-left: .4rem;
  padding: 0 .45rem;
  border: 1px solid var(--base01);
  border-radius: 999px;
  font-size: .75rem;
  color: var(--base1);
  vertical-align: middle;
}

.entry__pair { margin: 0 0 .4rem; }
.entry__outcome { color: var(--base2); margin: 0 0 .4rem; }
.entry__note { margin: 0 0 .4rem; white-space: normal; }

details.danger summary { cursor: pointer; color: var(--base1); }
details.danger[open] summary { margin-bottom: .6rem; }
.entry details.danger { margin-top: .6rem; font-size: .9rem; }
.entry__actions { margin: .6rem 0 0; font-size: .9rem; }

/* --- v2: the service report (2026-10-05) ------------------------------------ */

.report__tools { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1.2rem; margin: 0 0 1.2rem; }
.report__tools button { margin-top: 0; }
.report__about { color: var(--base1); font-size: .92rem; margin: 1rem 0 1.5rem; }

.report__unit,
.report__table { width: 100%; border-collapse: collapse; margin: 0 0 1.5rem; font-size: .92rem; }
.report__unit th { width: 7rem; text-align: left; font-weight: normal; color: var(--base1); }
.report__unit th,
.report__unit td,
.report__table th,
.report__table td {
  padding: .45rem .5rem .45rem 0;
  border-bottom: 1px solid rgba(88, 110, 117, .35);
  vertical-align: top;
}
.report__table th { text-align: left; color: var(--base1); font-weight: normal; font-size: .8rem; text-transform: uppercase; letter-spacing: .04em; }
.report__table td { color: var(--base1); }
.report__table .num { text-align: right; padding-right: .9rem; }
.report__table .entry__pair { margin: 0; }
.report__note { margin: .3rem 0 0; color: var(--base0); }

/*
 * 🔴 ON PAPER: the report and nothing else — no banner, no footer menu, no
 *    buttons, no queue notice. The "unofficial" statement is IN the report
 *    (LogbookViews::report()), so dropping the footer loses nothing.
 *    Black on white: a technician's printer, and a PDF someone forwards.
 */
@media print {
  .appbar, .disclaimer, .ack, .no-print, #queue-status, .notice { display: none !important; }
  body, main { background: #fff !important; color: #000 !important; padding: 0 !important; }
  main { max-width: none; }
  h1, h2, .report__about, .report__table th, .report__table td,
  .report__unit th, .report__unit td, .report__note, .meta { color: #000 !important; }
  h1 { border-bottom-color: #000; }
  .report__unit th, .report__unit td,
  .report__table th, .report__table td { border-bottom-color: #999; }
  .report__table tr { break-inside: avoid; }
  a { color: #000; text-decoration: none; }
}

@media (max-width: 480px) {
  .report__table { font-size: .85rem; }
  .report__unit th { width: 5.5rem; }
}
