/*
 * THE DEVICE'S OWN STYLESHEET — everything inside the screen, and nothing about where the
 * screen is.
 *
 * Two pages draw this device: the rig, where it is a phone sitting on a chart, and `boat.html`,
 * where it is the whole window. So the rules here stop at the panel's inside edge: `.device`
 * says how it stacks and measures itself and says nothing about how big it is, which is each
 * page's own business. A duplicate of the screen's type, spacing and colour in two pages would
 * be two things to keep in agreement, and the one that fell behind would be whichever was
 * edited second.
 *
 * THE TYPE IS IN `cqi` — a hundredth of this panel's own width — which is what `container-type`
 * on `.device` is for. A phone panel is 400 px on a desk and 230 px on a short window, and a
 * figure fixed in pixels that filled one overflows the other. Paddings and gaps scale with it,
 * or they would eat proportionally more of a narrow panel and break a size that only just fitted.
 */

.device {
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--sea);
  overflow-y: auto;
  /* So an alert can cover THIS screen and nothing else. A modal that covered the page would
     cover the rig it is sitting on, which is a desk and not a phone. */
  position: relative;
}

.device .bar {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px; border-bottom: 1px solid var(--panel2); font-size: 12px;
}
.device .bar .sp { flex: 1; }
.device .bar .disp { font-family: var(--disp); font-size: 16px; letter-spacing: 0.03em; }

/* The three orientations, and beside them the Course/Line/Auto override. */
.orient { display: flex; gap: 0; padding: 6px 12px 0; }
.orient button {
  flex: 1; background: none; border: 1px solid var(--panel2); color: var(--muted);
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.12em; text-transform: uppercase;
  padding: 5px 2px; cursor: pointer;
}
.orient button.on { color: var(--ink); border-color: var(--line); background: var(--panel2); }

.orient.views { padding-top: 8px; padding-bottom: 0; }
.orient.views button.on { color: var(--ok); border-color: var(--ok); }

/* The next-leg arrow, which carries the state in its colour. */
.leg {
  display: flex; align-items: center; gap: 8px; margin: 8px 12px;
  padding: 6px 10px; border: 2px solid var(--muted); border-radius: 5px; color: var(--muted);
}
.leg .disp { font-family: var(--disp); font-size: 17px; font-weight: 600; letter-spacing: 0.08em; }
.leg .mono { margin-left: auto; font-size: 15px; }
.leg.crossed { border-color: var(--ok); background: var(--ok); color: var(--sea); }
.leg.missed { border-color: var(--warn); color: var(--warn); border-width: 3px; }

.plot { display: block; width: 100%; height: auto; background: var(--sea); touch-action: none; }

.chartbar { display: flex; align-items: center; gap: 6px; padding: 4px 12px 0; }
.chartbar button {
  background: none; border: 1px solid var(--panel2); color: var(--muted);
  font-family: var(--mono); font-size: 12px; min-width: 30px; padding: 3px 6px; cursor: pointer;
}
.chartbar button:disabled { opacity: 0.4; cursor: default; }
.chartbar button.on { color: var(--ok); border-color: var(--ok); }
.chartbar select {
  margin-left: auto; background: var(--panel2); color: var(--ink); border: 1px solid var(--panel2);
  font-family: var(--mono); font-size: 10.5px; padding: 3px 4px; cursor: pointer;
}

/*
 * BTW, DTW, STARTED AND ELAPSED FILL THE PANEL. Equal columns across the whole width —
 * `grid-auto-flow: column` with `1fr` tracks, so the count follows the markup and the finished
 * state's third cell needs no second rule — and the ceilings are measured against the SYSTEM
 * font, because there is no webfont link on these pages and a size chosen for a face that may
 * not load is how a number ends up clipped on somebody else's phone.
 */
.device .readout {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  padding: 6px 3cqi; gap: 3cqi;
}
.device .readout .value { font-size: min(11cqi, 44px); line-height: 1.05; }
.device .readout.done .value { font-size: min(7cqi, 28px); }

.steer {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  gap: 3cqi; padding: 8px 3cqi 2px;
}
.steer .label {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--muted);
}
.steer .value {
  font-family: var(--disp); font-size: min(13.5cqi, 54px); font-weight: 600; line-height: 1;
}
.steer .unit { font-size: 0.3em; color: var(--muted); margin-left: 3px; }
.steer.stale .value { opacity: 0.45; }

/* Time to line: the one number worth a line to itself, and its colour is the warning. */
.ttl {
  display: flex; align-items: baseline; gap: 10px;
  margin: 6px 12px 2px; padding: 4px 12px;
  border-left: 4px solid currentColor;
}
.ttl .label {
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.2em;
  text-transform: uppercase; opacity: 0.75;
}
.ttl .value { font-family: var(--disp); font-size: 62px; font-weight: 700; line-height: 0.95; }
.ttl .unit { font-family: var(--mono); font-size: 16px; opacity: 0.75; }
.ttl.ok { color: var(--ok); }
.ttl.missing { color: var(--warn); }

/* The line being steered for, named — which is what a sailing instruction talks about. */
.wpt {
  display: flex; align-items: baseline; gap: 8px;
  margin: 8px 12px 0; padding: 5px 10px;
  border: 1px solid var(--panel2); border-left: 3px solid var(--line); border-radius: 4px;
}
.wpt .letter {
  font-family: var(--disp); font-size: 25px; font-weight: 700; color: var(--line);
  min-width: 22px; text-align: center;
}
.wpt .name { font-size: 25px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wpt .gate {
  margin-left: auto; font-size: 9.5px; letter-spacing: 0.14em; text-transform: uppercase;
}

.readout.stale .value { opacity: 0.45; }
/* FINAL is said by the colour, not by the label: a label that has to carry markup is a label
   saying too much, and the green row is already where somebody is looking. */
.readout.done .value { color: var(--ok); }
.readout.done .label { color: var(--ok); opacity: 0.8; }

.signal {
  margin: 0 12px 8px; padding: 4px 8px; font-size: 12px;
  border-left: 3px solid var(--warn); background: var(--panel);
}

.status { padding: 4px 12px 10px; font-size: 12.5px; color: var(--muted); }
.status.crossed { color: var(--ok); }
.status.missed { color: var(--warn); }

.crossings { padding: 0 12px 12px; font-size: 11px; }
.crossings li { padding: 1px 0; color: var(--muted); }

/* What is under the screens: leaving the course, and whatever the page adds beside it. */
.deck { display: flex; gap: 8px; padding: 0 12px 16px; }

/* The join screen. */
.join { padding: 14px 12px; }
.join h2 { margin: 14px 0 6px; font-size: 15px; color: var(--ink); }
.join label {
  display: block; font-family: var(--mono); font-size: 10px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--muted); margin: 8px 0 3px;
}
.join input, .join select {
  width: 100%; background: var(--panel2); color: var(--ink); font-family: var(--body);
  font-size: 14px; border: 1px solid var(--panel2); border-radius: 4px; padding: 6px 8px;
}
.join input:focus, .join select:focus { outline: none; border-color: var(--line); }
.join .pair { display: grid; grid-template-columns: 40% 60%; gap: 8px; }

button.go {
  width: 100%; margin-top: 14px; padding: 10px; border: none; border-radius: 5px;
  background: var(--line); color: var(--sea); font-family: var(--disp); font-size: 17px;
  font-weight: 600; letter-spacing: 0.06em; cursor: pointer;
}
button.go:disabled { background: var(--panel2); color: var(--muted); cursor: not-allowed; }

button.plain {
  background: var(--panel2); color: var(--ink); border: 1px solid var(--panel2);
  border-radius: 4px; padding: 5px 10px; font-family: var(--body); font-size: 13px; cursor: pointer;
}
button.plain:hover { border-color: var(--line); }
button.plain.on { border-color: var(--ok); color: var(--ok); }

/* ===================================================== what the dialog adds (§§9.1–9.3) */

/*
 * THE START, above every screen while there is one to count to. It is the one thing on this
 * device that is about a moment rather than a place, and in the five minutes it matters it is
 * the only thing anybody is looking at — so it is not on a screen you have to choose.
 */
.start {
  display: flex; align-items: baseline; gap: 2cqi;
  padding: 5px 3cqi; border-bottom: 1px solid var(--panel2);
  background: var(--panel); color: var(--muted);
}
.start .what {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.14em; text-transform: uppercase;
}
.start .value { font-family: var(--disp); font-size: min(9cqi, 36px); font-weight: 700; line-height: 1; }
.start .said { font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.start.warning { color: var(--toside); }
.start.warning .value { color: var(--toside); }
.start.racing { color: var(--ok); }
.start.racing .value { color: var(--ok); }
.start.postponed, .start.abandoned { color: var(--warn); }

/* The unread count rides on the Chat button: the one thing about the channel worth knowing
   from another screen. */
.orient.views .unread {
  background: var(--ok); color: var(--sea); border-radius: 7px;
  padding: 0 4px; font-size: 9px;
}

/* ------------------------------------------------------------------ the channel (§9.2) */

.log { flex: 1; min-height: 120px; overflow-y: auto; padding: 4px 0; }
.log .said { padding: 4px 12px; border-left: 3px solid transparent; }
.log .said .who {
  display: flex; align-items: center; gap: 6px; font-size: 10px; color: var(--muted);
}
.log .said .who .from { font-weight: 600; color: var(--ink); }
.log .said .who .kind { letter-spacing: 0.1em; text-transform: uppercase; opacity: 0.7; }
.log .said .text { font-size: 14px; }
.log .said.unseen { border-left-color: var(--toside); }
.log .said .badge {
  background: var(--toside); color: var(--sea); border-radius: 3px;
  padding: 0 4px; font-family: var(--mono); font-size: 9px;
}
/*
 * THE SAFETY THREE ARE NOT RACING MESSAGES and must not look like racing messages. They are on
 * the channel because it is the radio, and this is what a radio is for when the racing stops
 * mattering — so one must be impossible to scroll past.
 */
.log .said.safety { border-left-color: var(--warn); background: rgba(255, 95, 86, 0.08); }

.canned { display: flex; flex-wrap: wrap; gap: 5px; padding: 6px 12px 0; }
.canned.safety { padding-top: 4px; border-top: 1px dashed var(--panel2); margin-top: 4px; }
.canned.safety button { border-color: var(--warn); color: var(--warn); }
.compose { display: flex; gap: 6px; padding: 8px 12px 12px; }
.compose input {
  flex: 1; min-width: 0; background: var(--panel2); color: var(--ink);
  border: 1px solid var(--panel2); border-radius: 4px; padding: 6px 8px; font-size: 14px;
}
.compose input:focus { outline: none; border-color: var(--line); }

/* -------------------------------------------------------------- race progress (§9.1) */

.ladder { width: 100%; border-collapse: collapse; font-size: 13px; }
.ladder th {
  text-align: left; font-family: var(--mono); font-size: 9px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--muted); font-weight: 400; padding: 4px 6px;
  border-bottom: 1px solid var(--panel2);
}
.ladder td { padding: 3px 6px; border-bottom: 1px solid rgba(23, 41, 58, 0.5); }
.ladder td.place { color: var(--muted); }
.ladder tr.me td { background: var(--panel); }
.ladder tr.me td.place { color: var(--line); font-weight: 700; }
/* A boat whose last fix is old is drawn faded — the same rule the boat's own staleness
   follows, and the reason this screen ages rather than blanks. */
.ladder tr.stale td { opacity: 0.45; }

/* --------------------------------------------------------------- alerts (§9.3) */

/*
 * A course change or a flag changes what the boat is doing, so it interrupts — and dismissing
 * it IS the acknowledgement the server is waiting for. One gesture, not two.
 */
.alert {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  background: rgba(14, 26, 38, 0.82); padding: 8cqi; z-index: 5;
}
.alert .box {
  background: var(--panel); border: 2px solid var(--toside); border-radius: 8px;
  padding: 14px; width: 100%;
}
.alert .kind {
  font-size: 10px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--toside);
}
.alert .text { font-size: 17px; margin: 6px 0; }
.alert .when { font-size: 10.5px; color: var(--muted); }

/*
 * NOTHING INTERRUPTS AN APPROACH. While the Mark screen has the display the news shows as this
 * strip and the modal waits: a sailor thirty metres off a line at nine knots is doing the one
 * thing on this boat that cannot be interrupted, and a dialog over the plot at that moment is
 * worse than any news it could be carrying. It is not a quiet failure — it says what arrived
 * and it stays until it is read.
 */
.banner {
  display: flex; align-items: baseline; gap: 6px;
  margin: 0 12px 8px; padding: 5px 8px;
  border-left: 3px solid var(--toside); background: var(--panel); font-size: 12.5px;
}
.banner .kind { font-size: 9px; letter-spacing: 0.14em; color: var(--toside); }
.banner .text { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.banner .after { font-size: 9px; color: var(--muted); }
