:root {
  --bg: #05080c;
  --panel-bg: #0b1118;
  --panel-border: #1c2833;
  --text-main: #cdeeff;
  --text-dim: #5f7d8f;
  --accent: #37e6c4;
  --green: #2fd06a;
  --amber: #e8b93a;
  --red: #e5484d;
  --mvalue-safe: #0a2a4a;
  --mvalue-unsafe: #bcdfff;
  --display-blue: #008ef5;
  --display-value: #ffffff;
}

* {
  box-sizing: border-box;
}

/* ---------- Splash screen (disclaimer, shown once before the app) ---------- */

#splash-screen {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: var(--display-blue);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
}

.splash-content {
  max-width: 640px;
  text-align: center;
}

.splash-content p {
  color: #fff;
  font-size: 1rem;
  line-height: 1.6;
  margin: 0 0 1.5rem;
}

#splash-continue {
  background: #fff;
  color: var(--display-blue);
  border: none;
  border-radius: 4px;
  padding: 10px 20px;
  font-family: inherit;
  font-weight: bold;
  font-size: 1rem;
  cursor: pointer;
}

#splash-continue:hover {
  filter: brightness(0.95);
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text-main);
  font-family: 'Courier New', Courier, monospace;
  height: 100%;
}

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

#app {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: 8px;
  padding: 8px;
}

.panel {
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  padding: 8px;
}

/* ---------- Shared graph axis titles ---------- */

.graph-row {
  flex: 1;
  display: flex;
  align-items: stretch;
  gap: 6px;
  min-height: 0;
}

.axis-title-y {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.7rem;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
  flex-shrink: 0;
}

.axis-title-x {
  text-align: center;
  font-size: 0.7rem;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-top: 4px;
}

/* ---------- Dive profile graph ---------- */

#profile-panel {
  min-height: 260px;
  display: flex;
  flex-direction: column;
}

#profile-canvas {
  flex: 1;
  width: 100%;
  min-width: 0;
  /* Canvas is a replaced element -- flex items default to an automatic
     min-height equal to their intrinsic (attribute-set) size, which blocks
     flex:1 from ever shrinking it below whatever size ui.js last set via
     resizeProfileCanvas(). min-height:0 removes that floor. */
  min-height: 0;
  display: block;
  cursor: crosshair;
}

/* ---------- Computer display ---------- */

#display-panel {
  display: flex;
  justify-content: center;
}

/* The device bezel photo dictates the box's proportions (rather than being
   stretched to fit an externally-imposed box) -- width is set per
   breakpoint below, height always follows via aspect-ratio, so the photo
   is never distorted. */
.display-main {
  position: relative;
  width: 100%;
  max-width: 360px;
  aspect-ratio: 1158 / 940;
  background-image: url('dive-computer-display-bg.png');
  background-size: 100% 100%;
  background-repeat: no-repeat;
  border-radius: 8%;
  overflow: hidden;
}

/* Positioned to land exactly on the photographed screen's dark rectangle,
   measured directly from the source photo (inset % of the bezel crop's own
   width/height on each side) -- inset (not padding) so top/bottom resolve
   against height and left/right against width, keeping this aligned
   correctly across every breakpoint's box shape. Every child below is
   itself absolutely positioned within this box, using percentages measured
   directly from the reference photo (pixel-scanned, not eyeballed) --
   see the "Re-layout the computer display" plan for the source measurements. */
.display-content {
  position: absolute;
  top: 19.79%;
  right: 11.57%;
  bottom: 10.85%;
  left: 14.85%;
  /* Lets descendants size text/icons in cqmin (% of the SMALLER of this
     box's width/height) instead of fixed px, so they grow/shrink whenever
     the display resizes. cqmin specifically (not cqw, which only tracks
     width) matters because .display-main now fills its grid cell at
     whatever aspect ratio that cell has (see the desktop media query) --
     on a wide-but-short cell, cqw alone would keep growing with width even
     as available height shrank, pushing the bottom row of text past the
     screen/housing edge. container-type:size (not inline-size) is required
     for cqmin/cqh to resolve against height at all. */
  container-type: size;
  font-family: 'Segoe UI', Arial, sans-serif;
  color: var(--display-value);
}

.readout,
.selector {
  position: absolute;
  display: flex;
  flex-direction: column;
  text-align: left;
}

#depth-readout {
  left: 6%;
  top: 8%;
  width: 36%;
}

#ndl-readout {
  left: 49%;
  top: 8%;
  /* Wider than a plain "NDL" number needs, so the longer deco-stop/ERROR
     text (see .compact-value/.blink-error below) has room to run at a
     bigger, more legible font while still staying inside the screen (this
     box's right edge lands at 94%, short of the 100% screen boundary). */
  width: 45%;
}

.v-divider {
  position: absolute;
  left: 41.8%;
  top: 0;
  width: 0.8%;
  height: 43.3%;
  background: var(--display-blue);
}

.h-divider {
  position: absolute;
  left: 2.3%;
  top: 43.3%;
  width: 90.2%;
  height: 0.9%;
  background: var(--display-blue);
}

/* ---------- Ascent rate bar ---------- */

#ascent-bar {
  position: absolute;
  left: 4.2%;
  top: 48.8%;
  width: 4.6%;
  height: 33.7%;
  display: flex;
  flex-direction: column;
  gap: 6%;
}

.ascent-box {
  flex: 1;
  min-height: 0;
  border-radius: 2px;
  background: transparent;
  border: 1px solid var(--display-value);
}

.ascent-box.lit-green {
  background: var(--green);
  border-color: var(--green);
}

.ascent-box.lit-amber {
  background: var(--amber);
  border-color: var(--amber);
}

.ascent-box.lit-red {
  background: var(--red);
  border-color: var(--red);
}

#dive-time-readout {
  left: 16.5%;
  top: 47%;
  width: 36%;
  flex-direction: row;
  /* Top-aligned with the value (was baseline, which visually sat the
     smaller label text well below the value's top edge). */
  align-items: flex-start;
  gap: 8%;
}

/* top moved up from 57% (was reclaiming unused space between the h-divider
   at 44.2% and this box) to fit the new #gf-tier line; bottom (icon-row)
   stays put since height grew by the same amount top shrank. */
#gf-selector {
  left: 73.6%;
  top: 52%;
  width: 22%;
  height: 30%;
  justify-content: space-between;
}

/* Moved up from 63% to stay level with #altitude-selector, which needed the
   room for its relocated value -- Nitrox's own content is unchanged, it
   just has a bit more breathing room below now. */
/* flex-start + a fixed gap (not space-between) so the label->secondary-value
   spacing is identical between this and #altitude-selector regardless of
   their icon-rows' differing content -- that's what makes "Air"/"Nitrox"
   land exactly level with "0m" below Altitude's label. */
#nitrox-selector {
  left: 16.5%;
  top: 59%;
  width: 20%;
  height: 22%;
  justify-content: flex-start;
  gap: 1.5cqmin;
}

#altitude-selector {
  left: 42.6%;
  top: 59%;
  width: 22%;
  height: 24%;
  justify-content: flex-start;
  gap: 1.5cqmin;
}

.readout .label,
.selector .label {
  font-size: 3.9cqmin;
  color: var(--display-blue);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* "Surface Time" (during a surface interval) wraps to two lines instead of
   overlapping the 00:00 value — see updateDisplay() in ui.js. */
#dive-time-label.two-line {
  white-space: pre-line;
  line-height: 1.05;
}

#depth-readout .value,
#ndl-readout .value {
  font-size: 14.5cqmin;
  font-weight: bold;
  line-height: 1;
  white-space: nowrap;
}

#dive-time-readout .value {
  font-size: 8.2cqmin;
  font-weight: bold;
  white-space: nowrap;
}

.value .unit {
  font-size: 0.4em;
  font-weight: normal;
  margin-left: 1px;
}

.value.compact-value {
  font-size: 0.6em;
}

/* #ndl-readout .value's own font-size (14.5cqmin, above) is an ID selector,
   which beats .value.compact-value's plain two-class selector regardless of
   source order -- so the smaller size never actually applied here, and
   "10m / 19min"/"ERROR" overflowed the box's 20% width at the big new
   display size. These ID-scoped overrides win instead. */
/* Sized to use as much of the (widened, see #ndl-readout above) box's
   width as the longest realistic deco-stop string ("XXm / XXmin") allows. */
/* cqw (not cqmin): #ndl-readout's width is a fixed % of the container's
   width, so a font-size that's also purely width-based keeps the same
   text-width-to-box-width ratio at every aspect ratio. cqmin (mixing in
   height) let a tall-ish aspect ratio (e.g. 960x700) shrink this box's
   width faster than the height-driven font shrank, overflowing past the
   screen edge. Capped with cqh so a genuinely short row on a very
   wide-short screen still can't overflow vertically either. */
#ndl-readout .value.compact-value {
  font-size: min(6.9cqw, 14cqh);
}

.value.blink-error {
  color: var(--red);
  animation: blink-error 1s steps(1, start) infinite;
}

/* Matches .compact-value's size exactly, per explicit request -- "ERROR"
   is short enough that this is well within the box even at that size. */
#ndl-readout .value.blink-error {
  font-size: min(6.9cqw, 14cqh);
}

@keyframes blink-error {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

.icon-row {
  display: flex;
  align-items: center;
  gap: 2.4cqmin;
}

.selector .value {
  font-size: 5.8cqmin;
  font-weight: bold;
  white-space: nowrap;
}

/* Shared by #altitude-value and #nitrox-mode -- smaller/lighter than the
   main numeric readouts, sits directly under the label on both selectors. */
.secondary-value {
  font-size: 3.4cqmin;
  font-weight: normal;
}

/* White (not the label's blue) tier name shown under "GRADIENT" -- font-
   size tuned so "Conservative" (the widest of the three tier names) is
   about as wide as the "GRADIENT" label above it. */
.tier-label {
  color: var(--display-value);
  font-size: 3.3cqmin;
  white-space: nowrap;
}

.arrow-col {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: 8.7cqmin;
}

.arrow-col button {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  width: 0;
  height: 0;
  border-left: 2.4cqmin solid transparent;
  border-right: 2.4cqmin solid transparent;
  opacity: 0.9;
}

.arrow-col button:hover {
  opacity: 1;
}

.arrow-col button:first-child {
  border-bottom: 2.4cqmin solid var(--display-value);
}

.arrow-col button:last-child {
  border-top: 2.4cqmin solid var(--display-value);
}

.arrow-col button:hover:first-child {
  border-bottom-color: var(--display-blue);
}

.arrow-col button:hover:last-child {
  border-top-color: var(--display-blue);
}

.icon {
  width: 7.7cqmin;
  height: 4.8cqmin;
}

.sim-controls {
  display: grid;
  /* Middle column used to be `auto`, which sizes to the slider's full
     160px and never shrinks below it -- on a narrow controls-panel (now
     matched to the display's width, per the four-quadrant layout) that
     pushed the whole row wider than the container, so #reset-btn (in the
     rightmost 1fr column, justify-self:end) rendered past the panel's
     right edge instead of actually being right-aligned to it. minmax lets
     this column -- and the slider inside it -- give up width instead. */
  grid-template-columns: minmax(0, auto) minmax(50px, 160px) minmax(0, auto);
  align-items: center;
  gap: 10px;
}

#start-btn {
  background: var(--display-blue);
  color: #fff;
  border: none;
  border-radius: 4px;
  padding: 8px 16px;
  font-family: inherit;
  font-weight: bold;
  cursor: pointer;
  justify-self: start;
}

#start-btn:hover {
  filter: brightness(1.1);
}

#start-btn.btn-warning {
  background: var(--red);
  color: #fff;
}

#reset-btn {
  background: none;
  color: var(--display-blue);
  border: 1px solid var(--display-blue);
  border-radius: 4px;
  padding: 8px 16px;
  font-family: inherit;
  font-weight: bold;
  cursor: pointer;
  justify-self: end;
}

#reset-btn:hover {
  border-color: var(--display-blue);
  color: #fff;
  background: var(--display-blue);
}

/* Smaller/secondary sizing while a run is actively in progress (diving or
   an interval running) -- full-size everywhere else. */
#reset-btn.btn-compact {
  padding: 4px 10px;
  font-size: 0.75rem;
}

/* Stretches to fill its grid column (not justify-self:center / content-
   sized) so the slider's percentage-ish flex sizing below has a real,
   non-circular width to shrink against; justify-content still centers the
   label/slider/value as a group within that width. */
.speed-control {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-width: 0;
}

/* Grows up to 160px on wide-enough screens, shrinks below it once space
   gets tight -- instead of a fixed 160px forcing the whole row wider than
   the container (and #reset-btn off the edge). */
#speed-slider {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 160px;
}

.speed-control .value {
  min-width: 3em;
  text-align: right;
}

/* Narrow phones: let the row wrap to multiple lines rather than crowd the
   fixed-width slider -- the slider's own length never changes, just the
   row's wrapping behavior at this breakpoint. */
@media (max-width: 420px) {
  .sim-controls {
    grid-template-columns: 1fr;
    justify-items: stretch;
  }
  #start-btn, #reset-btn {
    justify-self: stretch;
  }
  .speed-control {
    justify-self: stretch;
  }
}

/* ---------- Controls box (start/pause + speed, and the warning/log area) ---------- */

#controls-panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  /* Without this, the log's overflow-y:auto (below) can't actually clip --
     a flex item's default min-height is auto (content-based), which on
     desktop lets this panel's natural content height propagate up into the
     grid row's own auto-minimum, silently growing that row (and everything
     else sharing it, including #bars-panel) as the log fills with more
     entries over a long simulation, instead of staying fixed and letting
     the log scroll internally as intended. */
  min-height: 0;
}

#log-box {
  height: calc(1.3em * 5 + 16px); /* fixed to ~5 lines; older entries scroll */
  overflow-y: auto;
  background: #060b10;
  border: 1px solid var(--panel-border);
  border-radius: 4px;
  padding: 8px 10px;
  font-size: 0.8rem;
  line-height: 1.3em;
}

.log-entry {
  color: #fff;
  padding: 2px 0;
  border-bottom: 1px solid var(--panel-border);
}

.log-entry.warning {
  color: var(--red);
  border-bottom-color: rgba(229, 72, 77, 0.15);
}

.log-entry:last-child {
  border-bottom: none;
}

/* ---------- Compartment bars ---------- */

#bars-panel {
  display: flex;
  flex-direction: column;
  /* No flex-grow here (on mobile #app is a flex column) — otherwise this
     panel stretches to fill all leftover viewport height, leaving a big
     empty gap above the drawn bars. min-height keeps it comfortably sized
     without over-stretching; ignored by the desktop grid layout below,
     which sizes this panel via its own grid row instead. */
  min-height: 260px;
}

#bars-panel .label {
  font-size: 0.7rem;
  color: var(--text-dim);
  text-transform: uppercase;
  margin-bottom: 4px;
}

#bars-wrap {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 180px;
  min-width: 0;
}

#bars-canvas {
  flex: 1;
  width: 100%;
  /* Same replaced-element flex-shrink floor as #profile-canvas above. */
  min-height: 0;
  display: block;
  border: 1px solid var(--panel-border);
  border-radius: 2px;
}

#bars-labels {
  display: flex;
  padding-left: 56px; /* matches BARS_LEFT_PAD in ui.js */
}

#bars-labels span {
  flex: 1;
  text-align: center;
  font-size: 0.6rem;
  color: var(--text-dim);
}

#bars-axis-legend {
  text-align: center;
  font-size: 0.65rem;
  color: var(--text-dim);
  margin-top: 4px;
  letter-spacing: 0.03em;
}

/* ---------- Layout: mobile default (stacked) ---------- */

#profile-panel {
  order: 1;
}
#display-panel {
  order: 2;
}
#controls-panel {
  order: 3;
}
#bars-panel {
  order: 4;
}

/* ---------- Layout: desktop ---------- */

@media (min-width: 900px) {
  /* Everything must fit within one screen -- a real (not just min-) height
     on body/#app is what lets the grid's 1fr/vh rows below actually size
     against the viewport instead of ballooning to their content's natural
     size (which is what was happening before: #app had no definite height,
     so the bars-panel row and its canvas grew arbitrarily large). */
  body {
    height: 100vh;
    overflow: hidden;
  }

  /* Four quadrants: dive planning graph + computer display on top, the
     compartment loading graph + start/reset/notifications on bottom.
     Row 1's height is the old (row1 + gap + row2) combined -- profile-panel
     used to span both of those rows, so folding them into one row keeps
     its height exactly as it was, now that display-panel/controls-panel
     no longer need a second, separate short row of their own. */
  #app {
    display: grid;
    grid-template-columns: 1.4fr 1fr;
    /* minmax(0, 1fr), not bare 1fr -- a bare `1fr` track's implicit minimum
       is auto (its content's min-content size), which without the explicit
       0 floor can still grow this row past 1fr to fit a tall #log-box, even
       with min-height:0 set on #controls-panel above. */
    grid-template-rows: minmax(388px, calc(30vh + 198px)) minmax(0, 1fr);
    height: 100vh;
  }

  #profile-panel {
    grid-column: 1;
    grid-row: 1;
    order: initial;
    min-height: 388px;
  }

  #display-panel {
    grid-column: 2;
    grid-row: 1;
    order: initial;
  }

  /* Fills the entire quadrant now (no more fixed width/aspect-ratio keeping
     it small and centered) -- the bezel photo stretches to match via
     background-size:100% 100% (already set in the base rule), same
     "scale to fit the space" tradeoff already accepted project-wide rather
     than letterboxing or cropping it. */
  .display-main {
    width: 100%;
    height: 100%;
    max-width: none;
    aspect-ratio: auto;
  }

  #controls-panel {
    grid-column: 2;
    grid-row: 2;
    order: initial;
  }

  /* This box is now as tall as the compartment loading graph next to it
     (row 2's full height) instead of a short fixed row -- let the log grow
     to fill that instead of leaving dead space below a fixed 5-line box. */
  #log-box {
    flex: 1;
    height: auto;
  }

  /* Same column as profile-panel now (was col 1/span 2, full width) --
     matches the dive planning graph's width instead of spanning under both
     columns. The canvas drawing (drawBars in ui.js) already reads its own
     live rendered width every frame, so the compartment content rescales
     to the narrower space with no JS changes needed. */
  #bars-panel {
    grid-column: 1;
    grid-row: 2;
    order: initial;
    min-height: 0; /* the mobile min-height would otherwise fight the grid row's own sizing */
  }

  #bars-wrap {
    /* Lower than the mobile floor (180px) so the now-properly-computed 1fr
       row (see body/#app above) can shrink this panel on shorter desktop
       viewports without being forced into overflow by this floor. */
    min-height: 120px;
  }
}
