/* Crewwize — the account pages and the fleet screens (REQ-013 §6, §7).
 *
 * Loaded after crewwize.css, which owns the palette, the type and every control
 * on this page. Nothing here redefines a token; this sheet is layout only.
 *
 * Two surfaces share it because they are the same surface at different depths:
 * signing in and planning a voyage are both done sitting down, ashore, on a
 * laptop or a phone, with the network up. The app aboard is the other kind of
 * screen entirely and does not load this (D-92).
 */

/* --- the account card ------------------------------------------------------ */
/*
 * Sign in, create an account, reset a password, confirm an address. Four pages a
 * person meets once each, usually on a phone, usually while trying to do
 * something else — so they are one column, one card, one obvious action (D-94).
 *
 * The card is centred and capped at 27rem because a login form stretched across
 * a 27-inch monitor is the shape this design replaced: the eye had to travel the
 * whole width to get from the label to the field, and the page looked abandoned
 * on the right-hand two thirds.
 */

.auth-wrap {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: clamp(1.25rem, 5vw, 3.5rem) clamp(1rem, 4vw, 2rem);
  /* A quiet wash of the brand navy behind the card, so the account pages read as
   * a continuation of the public site rather than a bare form. */
  background:
    radial-gradient(120% 90% at 50% 0%,
      color-mix(in srgb, var(--navy) 10%, var(--bg)) 0%,
      var(--bg) 70%);
}

.auth {
  width: 100%;
  max-width: 27rem;
  background: var(--card);
  border: 1px solid var(--card-line);
  border-radius: var(--radius-lg);
  padding: clamp(1.25rem, 5vw, 2rem);
}

.auth h1 {
  font-size: clamp(1.5rem, 5vw, 1.85rem);
  margin-bottom: .5rem;
}
.auth .lede { font-size: .98rem; margin-bottom: 1.4rem; }
.auth .lede:last-of-type { margin-bottom: 1.4rem; }
.auth p { font-size: .95rem; }

.auth .stack { margin: 1.4rem 0 0; }
/* The one action on the page fills the card. On these four pages there is never
 * a second thing to press at the same level, so there is nothing for it to
 * crowd — and a full-width target is the easiest thing to hit one-handed. */
.auth .stack > button { width: 100%; margin-top: .3rem; }
.auth .button { width: 100%; margin-top: .4rem; }

/* On a phone the card gives up its border and its rounding and becomes the page.
 * A boxed form inside a screen the same colour is a border for its own sake. */
@media (max-width: 30rem) {
  .auth-wrap { padding-inline: 0; padding-top: 1.25rem; justify-content: flex-start; }
  .auth {
    border-inline: 0;
    border-top: 0;
    border-radius: 0;
    padding-inline: 1.15rem;
  }
}

/* The alternate route — "no account?", "forgotten your password?" — closes the
 * card behind a hairline. It is deliberately not a button: exactly one thing on
 * these pages should look pressable, and it is the one that submits the form. */
.auth-foot {
  margin: 1.6rem 0 0;
  padding-top: 1.1rem;
  border-top: 1px solid var(--card-line);
  font-size: .92rem;
  color: var(--fg-2);
}
.auth-foot a { color: var(--fg); }

/* Inside the card the notice sits under the heading and above the form, so its
 * bottom margin is the form's top margin and not a second gap. */
.auth .notice { margin-bottom: 0; font-size: .93rem; }

/* --- the application shell (D-121) ----------------------------------------- */
/*
 * Sidebar beside sheet, under the one navy bar. Grid rather than flex so the
 * sheet's column is the one that gives: a sidebar that shrinks turns "Add a
 * vessel" into two lines and then into an ellipsis, and a menu you have to read
 * twice is worse than no menu.
 *
 * The fold is a body class set server-side from a cookie, because CSS cannot
 * remember anything across a navigation and this service serves exactly one
 * script — passkey.js, for a ceremony that cannot be a form (D-96, R-94).
 */

.shell {
  flex: 1;
  display: grid;
  grid-template-columns: var(--side-w) minmax(0, 1fr);
  align-items: start;
}
.side-folded .shell { grid-template-columns: 0 minmax(0, 1fr); }

.side {
  position: sticky;
  /* Under the bar, which is itself sticky at 0. */
  top: 68px;
  align-self: start;
  max-height: calc(100vh - 68px);
  overflow-y: auto;
  padding: 1.1rem .7rem;
  border-right: 1px solid var(--rule);
  background: var(--bg-alt);
}
.side-folded .side {
  /* Folded away rather than hidden: `display: none` would take it out of the
   * tab order abruptly, and a menu that vanishes mid-navigation is disorienting
   * in a way a menu that slides is not. It is still hidden from assistive
   * technology, because a zero-width menu is not a menu. */
  padding-inline: 0;
  border-right: 0;
  overflow: hidden;
  visibility: hidden;
}

.side ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .15rem; }
.side a {
  display: flex;
  align-items: center;
  gap: .7rem;
  min-height: var(--tap);
  padding: .4rem .7rem;
  border-radius: var(--radius-sm);
  color: var(--fg-2);
  text-decoration: none;
  font-size: .96rem;
  white-space: nowrap;
}
.side a:hover { background: var(--card); color: var(--fg); }
/* The page you are on, marked by the one accent this design spends (D-93). It
 * is a bar rather than a filled row: a filled row on a menu reads as a button
 * somebody forgot to press. */
.side a.on {
  background: var(--card);
  color: var(--fg);
  font-weight: 600;
  box-shadow: inset 3px 0 0 var(--accent);
}

/* On a phone the sidebar is a strip across the top instead of a column: 15rem of
 * a 390 px screen is most of it, and a menu that leaves a third of the width for
 * the page is not a layout, it is an argument. */
@media (max-width: 52rem) {
  .shell, .side-folded .shell { grid-template-columns: minmax(0, 1fr); }
  .side {
    position: static;
    max-height: none;
    border-right: 0;
    border-bottom: 1px solid var(--rule);
    padding: .5rem .6rem;
  }
  .side ul { grid-auto-flow: column; grid-auto-columns: max-content; overflow-x: auto; }
  .side-folded .side { display: none; visibility: visible; }
}

/* --- the fleet sheet ------------------------------------------------------- */

.sheet {
  width: 100%;
  max-width: 62rem;
  margin-inline: auto;
  padding: clamp(1.5rem, 4vw, 2.5rem) clamp(1rem, 4vw, 2rem) 3rem;
}
.sheet h1 { margin: 0 0 .5rem; }
.sheet h3 { margin: 1.6rem 0 .5rem; font-size: 1rem; color: var(--fg-2); }
.sheet .stack { max-width: 34rem; margin: 1.5rem 0; }

/* --- sections are cards (D-121) -------------------------------------------- */
/*
 * Every section of a fleet page is a card, and the horizontal rules that used to
 * separate them are gone. A rule says "the thing above ended"; a card says "this
 * is one thing" — and on the vessel page, where a crew list, a list of voyages
 * and an invitation form sit under one heading each, the second is what a reader
 * needs. It also gives each block somewhere to put its own quiet explanation
 * without that paragraph looking like it belongs to whatever came next.
 */
.sheet > section {
  background: var(--card);
  border: 1px solid var(--card-line);
  border-radius: var(--radius-lg);
  padding: clamp(1rem, 3vw, 1.5rem);
  margin-bottom: 1.2rem;
}
.sheet > section > h2 { margin: 0 0 .5rem; font-size: 1.18rem; }
.sheet > section > :last-child { margin-bottom: 0; }
.sheet h2 { margin: 2rem 0 .6rem; font-size: 1.2rem; }

/* A card inside a card would be two borders and no more meaning, so the cards
 * that are themselves list items keep their own frame and lose the outer one. */
.sheet > section > .cards .card { background: var(--bg-alt); }

.crumb { margin: 0 0 .8rem; font-size: .9rem; color: var(--fg-2); }
.crumb a { color: var(--fg); }

.meta {
  color: var(--fg-2);
  margin: 0 0 1.2rem;
  display: flex;
  gap: .6rem;
  align-items: center;
  flex-wrap: wrap;
  font-size: .95rem;
}

.sheet code, .meta code {
  background: var(--bg-alt);
  border: 1px solid var(--rule);
  border-radius: 5px;
  padding: .1rem .4rem;
  font-size: .88rem;
}

/* --- cards, rows, tables --------------------------------------------------- */

.cards {
  list-style: none;
  padding: 0;
  margin: 1.4rem 0;
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
}
.card {
  border: 1px solid var(--card-line);
  border-radius: var(--radius);
  background: var(--card);
  padding: 1rem 1.1rem;
}
.card h2 { margin: 0 0 .4rem; font-size: 1.05rem; }
.card .meta { margin: 0; }

.rows { list-style: none; padding: 0; margin: 1rem 0; }
.rows li {
  padding: .6rem 0;
  border-bottom: 1px solid var(--rule);
  display: flex;
  gap: .7rem;
  align-items: center;
  flex-wrap: wrap;
}

form.inline.row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: .5rem 0;
  border-bottom: 1px solid var(--rule);
  max-width: 34rem;
}

.list { margin: 0; padding-left: 1.1rem; display: grid; gap: .5rem; max-width: 72ch; }
.list li::marker { color: var(--accent); }

.steps { margin: 1rem 0 1.4rem; padding-left: 1.3rem; max-width: 40rem; }
.steps li { margin-bottom: .5rem; line-height: 1.55; }
.steps li::marker { font-family: var(--mono); font-weight: 700; color: var(--accent); }

/* Wide content scrolls in its own box rather than making the page scroll
 * sideways — a crew list on a phone is exactly the case that would. */
.sheet table {
  width: 100%;
  border-collapse: collapse;
  margin: .8rem 0;
  display: block;
  overflow-x: auto;
}
.sheet thead th {
  text-align: left;
  font-size: .8rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--fg-2);
  border-bottom: 1px solid var(--rule);
  padding: .4rem .6rem .4rem 0;
  font-weight: 600;
  white-space: nowrap;
}
.sheet td {
  padding: .55rem .6rem .55rem 0;
  border-bottom: 1px solid var(--rule);
  vertical-align: baseline;
}
.sheet td.right, .sheet th.right { text-align: right; padding-right: 0; }

/* --- the claim code -------------------------------------------------------- */
/*
 * Shown once and read off the screen onto a keypad on a boat (REQ-009 §8).
 * Everything here serves being retyped correctly: monospace so the character
 * widths line up, generous letter-spacing so a group of four cannot be
 * miscounted, and user-select:all so a tap selects the whole thing rather than
 * one group. It is deliberately larger than any other text in the service.
 */
.code-block { margin: 1.4rem 0; }
code.claim {
  display: inline-block;
  font-size: clamp(1.3rem, 6vw, 2rem);
  letter-spacing: .12em;
  padding: .7rem 1rem;
  user-select: all;
  background: var(--bg-alt);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  word-break: break-all;
}

/* --- recovery codes -------------------------------------------------------- */
/*
 * Ten one-time codes, shown once (§5.5). Same treatment as the claim code and
 * for the same reason: these are read off a screen and written onto paper or
 * into a phone, so the character widths have to line up and a group of four must
 * not be miscountable. Larger than the surrounding text, deliberately.
 */
.codes {
  list-style: decimal;
  margin: 1.4rem 0;
  padding-left: 2.2rem;
  display: grid;
  gap: .5rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
  max-width: 34rem;
}
.codes li {
  font-family: var(--mono);
  font-size: 1.05rem;
  letter-spacing: .08em;
  user-select: all;
  color: var(--fg);
}
.codes li::marker { color: var(--fg-2); font-size: .8rem; }

.codes-h { margin: 1.5rem 0 .5rem; font-size: 1.15rem; }

/* The account card is one column and one action; the codes panel replaces the
 * form inside it rather than becoming a second page, because a redirect between
 * "here are your codes" and anything else is a chance to lose them. */
.auth .codes { max-width: none; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.auth .codes li { font-size: .98rem; }

/* The operator page (0014). Layout only — every colour here is a token from
   crewwize.css, which TestOnlyTheFoundationDefinesTokens enforces. */
.ops { width: 100%; border-collapse: collapse; }
.ops th,
.ops td { padding: .5rem .6rem; border-bottom: 1px solid var(--rule); text-align: left; vertical-align: top; }
.ops thead th { font-size: .82rem; letter-spacing: .04em; text-transform: uppercase; color: var(--fg-2); }
.ops tbody th { font-weight: 600; width: 18rem; }

/* "no data" must not look like a value. It is the same weight as body text and
   deliberately not red: an unreadable source is a gap in what we know, not an
   alarm, and colouring it as danger would train the reader to ignore real ones. */
.nodata { color: var(--fg-2); font-style: italic; }

.tag.ok  { background: var(--ok); color: var(--paper); }
.tag.bad { background: var(--danger); color: var(--paper); }

/* --- the menu behind the avatar (D-138) ------------------------------------ */
/*
 * The app's four menu items, ashore. A <details> and not a script: a disclosure
 * is native, keyboard-reachable, closes on Escape, and keeps this service at one
 * script — the passkey ceremony, which cannot be a form (D-96, R-94).
 */
.usermenu { position: relative; margin-left: auto; }
.usermenu > summary {
  display: flex; align-items: center; gap: .55rem;
  min-height: var(--tap); padding: .2rem .35rem;
  border-radius: var(--radius-sm); cursor: pointer; list-style: none;
}
.usermenu > summary::-webkit-details-marker { display: none; }
.usermenu > summary::marker { content: ""; }
.usermenu > summary:hover { background: rgba(255, 255, 255, .1); }
.usermenu-panel {
  position: absolute; right: 0; top: calc(100% + .5rem); z-index: 20;
  min-width: 15rem;
  background: var(--card); color: var(--fg);
  border: 1px solid var(--card-line); border-radius: var(--radius);
  box-shadow: 0 12px 30px -14px rgba(0, 0, 0, .45);
  padding: .5rem;
}
.usermenu-who { margin: 0 0 .4rem; padding: .35rem .6rem .55rem;
  border-bottom: 1px solid var(--rule); font-weight: 600; font-size: .95rem; }
.usermenu-panel ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .1rem; }
.usermenu-panel a, .usermenu-out {
  display: flex; align-items: center; gap: .7rem; width: 100%;
  min-height: var(--tap); padding: .4rem .6rem;
  border: 0; border-radius: var(--radius-sm); background: none;
  color: var(--fg-2); text-decoration: none; font: inherit; font-size: .95rem;
  text-align: left; cursor: pointer;
}
.usermenu-panel a:hover, .usermenu-out:hover { background: var(--bg-alt); color: var(--fg); }
.usermenu-panel a.on { color: var(--fg); font-weight: 600; box-shadow: inset 3px 0 0 var(--accent); }
.usermenu-out { margin-top: .3rem; border-top: 1px solid var(--rule); border-radius: 0 0 var(--radius-sm) var(--radius-sm); }

/* On a phone the panel is the width of the screen rather than a 15rem card
 * hanging off the right edge, where half of it would be off-screen. */
@media (max-width: 30rem) {
  .usermenu { position: static; }
  .usermenu-panel { left: .5rem; right: .5rem; min-width: 0; }
}

/* --- page and card headings ------------------------------------------------ */

.page-h { display: flex; align-items: baseline; justify-content: space-between;
          gap: 1rem; margin: 0 0 .6rem; flex-wrap: wrap; }
.card-h { display: flex; align-items: baseline; justify-content: space-between;
          gap: 1rem; margin: 0 0 .5rem; flex-wrap: wrap; }
.card-h h2 { margin: 0; font-size: 1.18rem; }
.card-h.later { margin-top: 1.6rem; }

/* --- the specification grid (REQ-016 §5.1) --------------------------------- */

.spec { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
        gap: .95rem 1.4rem; margin: 0 0 1rem; }
.spec > div { display: grid; gap: .12rem; align-content: start; }
.spec dt { font-size: .78rem; letter-spacing: .04em; text-transform: uppercase;
           font-weight: 600; color: var(--fg-2); }
.spec dd { margin: 0; font-size: .98rem; font-weight: 600; }
.spec dd code { font-weight: 400; }
.unit { font-weight: 400; color: var(--fg-2); font-size: .88em; }

/* A field nobody filled in. Deliberately not red and deliberately not a dash:
 * an absence is a gap in what we know, not an alarm and not a "none". */
.none { font-weight: 400; color: var(--fg-2); font-style: italic; }
.figure { font-variant-numeric: tabular-nums; }

@media (max-width: 52rem) { .spec { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 30rem) { .spec { grid-template-columns: minmax(0, 1fr); } }

/* --- a named absence -------------------------------------------------------- */
/*
 * The house style for "there is nothing here yet", used everywhere a list can be
 * empty. Dashed rather than solid so it does not read as a card with content,
 * and it always says what WOULD be here — an empty box teaches nothing.
 */
.empty {
  border: 1px dashed var(--card-line); border-radius: var(--radius);
  background: var(--bg-alt); padding: .9rem 1rem;
  color: var(--fg-2); font-size: .9rem; line-height: 1.5;
}
.empty strong { color: var(--fg); }
.empty + .fine, .empty + p { margin-top: .9rem; }

/* --- people ----------------------------------------------------------------- */

.people { list-style: none; margin: 1rem 0 0; padding: 0; display: grid;
          gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr)); }
.person-card { border: 1px solid var(--card-line); border-radius: var(--radius);
               background: var(--bg-alt); padding: 1rem 1.05rem;
               display: grid; gap: .6rem; align-content: start; }
.person-card .top { display: flex; align-items: center; gap: .7rem; }
.person-card .nm { font-weight: 650; font-size: 1.02rem; line-height: 1.2; }
.person-card .sub { font-size: .86rem; color: var(--fg-2); }
.tags { display: flex; flex-wrap: wrap; gap: .3rem; }

/* The monogram, matching the boat's roster and the header exactly. */
.chip { display: inline-flex; align-items: center; justify-content: center;
        width: 28px; height: 28px; border-radius: 50%; color: #fff; flex: none;
        font-family: var(--mono); font-size: .68rem; font-weight: 700; }
.chip.lg { width: 40px; height: 40px; font-size: .8rem; }

.rows .when { margin-left: auto; font-size: .88rem; color: var(--fg-2); }

/* --- adding to the safety list ---------------------------------------------- */

.safety-add { margin-top: 1.4rem; padding-top: 1.2rem; border-top: 1px solid var(--rule); }
.safety-add .pair label { flex: 1 1 12rem; }

/* The vessel's pictures (REQ-016 §5.2, D-134).
   Colour and radius come from the foundation's tokens; spacing is written in rem
   the way the rest of this stylesheet writes it, because the foundation defines
   no spacing scale and inventing one HERE would be defining a token in a layout
   stylesheet, which D-91 forbids and TestOnlyTheFoundationDefinesTokens fails
   on. Adding a spacing scale is a change to crewwize.css and a decision. */
.canvas {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 21 / 8;
  object-fit: cover;
  border-radius: var(--radius);
  margin-bottom: 1.2rem;
}
.gallery {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: 1rem;
}
.gallery > li {
  display: flex;
  flex-direction: column;
  gap: .45rem;
}
.gallery img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius);
  background: var(--bg-alt);
}
/* A mirrored picture or clip (REQ-012 §7). A <figure>, because it carries who
   took it and when the boat says it was taken — and deliberately no control:
   for a picture on that page, this is the copy. */
.gallery > .shot {
  display: flex;
  flex-direction: column;
  gap: .45rem;
}
.gallery > .shot img,
.gallery > .shot video {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius);
  background: var(--bg-alt);
}
.gallery > .shot figcaption { display: flex; flex-direction: column; gap: .15rem; }

.gallery-c { display: flex; flex-wrap: wrap; align-items: center; gap: .45rem; }
.gallery-a { display: flex; flex-wrap: wrap; gap: .7rem; }

/* A superseded document is kept and shown as superseded, never hidden (D-137).
   Dimmed rather than removed, because "what was valid last March" is exactly the
   question an audit puts. */
tr.superseded td { opacity: .62; }

/* Three tabs, three real links (REQ-016 §6). Colour and radius come from the
   foundation's tokens; the spacing is written in rem the way the rest of this
   file writes it, because crewwize.css defines no spacing scale and inventing
   one here would be defining a token in a layout stylesheet (D-91).

   The active tab is marked by weight and a rule, never by colour alone: the
   accent never means "you are here" any more than it means danger (D-93), and a
   distinction carried only in hue is one some readers do not get. */
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 1.2rem;
}
.tabs a {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  /* ≥ 44 px of tappable height, D-94, without a fixed height that would clip a
     wrapped label. */
  min-height: var(--tap);
  padding: .5rem .9rem;
  color: var(--ink-2);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.tabs a:hover { color: var(--ink); }
.tabs a.on {
  color: var(--ink);
  font-weight: 600;
  border-bottom-color: var(--accent);
}

/* The leg-by-person matrix (REQ-016 §6.2, D-129).

   A voyage with six legs is wider than a phone. Wide content scrolls inside its
   own container so the page body never scrolls sideways — losing the name column
   off the left edge is how a matrix becomes unreadable. */
.scroll-x {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.scroll-x table { min-width: 100%; }

/* A checkbox cell. The control is enlarged rather than the cell padded, because
   the thing being aimed at on a phone is the box itself (D-94). */
td.mid, th.mid { text-align: center; }
td.mid input[type="checkbox"] {
  width: 1.35rem;
  height: 1.35rem;
  margin: .3rem;
}

/* Choosing legs when asking for a berth (REQ-016 §6.3).

   A fieldset because these checkboxes are one question with several answers, and
   a screen reader that reads the legend before each box is the whole point of
   the element. */
fieldset {
  border: 1px solid var(--rule);
  border-radius: .5rem;
  padding: .6rem .9rem .9rem;
  margin: 0;
}
fieldset legend { padding: 0 .4rem; color: var(--ink-2); font-size: .85rem; }
fieldset label.row {
  display: flex;
  align-items: center;
  gap: .6rem;
  /* ≥ 44 px of tappable row, D-94: the label is the target, not just the box. */
  min-height: var(--tap);
}
fieldset label.row input[type="checkbox"] { width: 1.35rem; height: 1.35rem; }

/* The watch plan (REQ-016 §6.5).

   A rota is read at a glance and edited rarely, so each leg is a block with its
   own heading rather than a row in one wide table — the leg is the thing that
   changes the rota, and it deserves to be the thing that structures the page. */
.rota-leg, .rota-pattern {
  border-top: 1px solid var(--rule);
  padding-top: 1rem;
  margin-top: 1.2rem;
}
.rota-leg h3, .rota-pattern h3 { margin: 0 0 .6rem; font-size: 1rem; }
.rota-leg table { margin-bottom: .9rem; }

/* The named watches, as a plain list of chips. */
ul.chips { list-style: none; margin: 0 0 .9rem; padding: 0; display: flex;
           flex-wrap: wrap; gap: .5rem 1rem; }
ul.chips li { display: inline-flex; align-items: center; gap: .4rem; }

label.inline { display: inline-flex; align-items: center; gap: .5rem; margin-right: 1rem; }
label.inline select, label.inline input { min-height: var(--tap); }

/* The chart a vessel carries (REQ-016 §7.5, D-165).

   A zoom with no script. Three radios sit before the frame, so a `:checked ~`
   rule can set the image's width, and the frame scrolls — which is the pan.
   This service serves exactly one script (D-96, R-94) and a picture of the
   Havel is not the reason to serve a second. */
.chart-zoom > input[type="radio"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.chart-zoom-bar {
  display: flex;
  align-items: center;
  gap: .5rem;
  margin: .8rem 0 .4rem;
  flex-wrap: wrap;
}
.chart-zoom-bar label {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap);
  min-width: var(--tap);
  padding: 0 .8rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
/* The level in force, marked on the control rather than only in the picture. */
#cz1:checked ~ .chart-zoom-bar label[for="cz1"],
#cz2:checked ~ .chart-zoom-bar label[for="cz2"],
#cz4:checked ~ .chart-zoom-bar label[for="cz4"] {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}
/* Keyboard focus, which the hidden radio would otherwise take out of sight. */
#cz1:focus-visible ~ .chart-zoom-bar label[for="cz1"],
#cz2:focus-visible ~ .chart-zoom-bar label[for="cz2"],
#cz4:focus-visible ~ .chart-zoom-bar label[for="cz4"] {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.chart-scroll {
  overflow: auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  max-height: 70vh;
  -webkit-overflow-scrolling: touch;
}
.chart-pic {
  display: block;
  width: 100%;
  height: auto;
  /* Sharp rather than smoothed when magnified: a soft coastline invites the
     reader to believe there is detail there. There is not. */
  image-rendering: pixelated;
}
#cz2:checked ~ .chart-scroll .chart-pic { width: 200%; max-width: none; }
#cz4:checked ~ .chart-scroll .chart-pic { width: 400%; max-width: none; }

/* The consent somebody agreed to, quoted rather than paraphrased (D-132).
 *
 * It is set as a quotation because that is what it is: the exact sentence, so a
 * person can read what they are agreeing to and can read it back afterwards. A
 * consent whose wording nobody can produce is a consent nobody gave. */
.consent {
  margin: .9rem 0;
  padding: .8rem 1rem;
  border-left: 3px solid var(--accent);
  background: var(--bg-alt);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-style: italic;
}

/* What a crew member wrote for whoever is helping them. Their words, their line
 * breaks: pre-line, because a list typed on four lines that renders as one
 * paragraph is slower to read at exactly the moment it is read (R-153). */
.responder {
  white-space: pre-line;
  padding: .8rem 1rem;
  border: 1px solid var(--card-line);
  border-radius: var(--radius-sm);
  background: var(--card);
  margin: 0 0 .8rem;
}

/* The backoffice desk (D-168, REQ-009 §13.7).
   Component rules only — no token is defined here (D-91). */

/* A customer's message, shown as they typed it. pre-wrap rather than pre:
   a mail body has its own line breaks, which must be kept, but a long line
   must not push the page sideways — wide content scrolls inside its own box
   and the page body never scrolls horizontally. */
.letter {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  margin: 0;
  font: inherit;
  max-height: 32rem;
  overflow-y: auto;
}

/* Unanswered. Weight and not colour: red is wrong and green is confirmed
   (D-93), and "nobody has replied yet" is neither. */
.rows tr.unread td { font-weight: 600; }

.nowrap { white-space: nowrap; }

/* The preview under a subject, on its own line so a long one cannot push the
   date column off a narrow screen. */
.rows td .fine { display: block; }
