/* FTSR JS port — mobile-first responsive styles.
   Touch targets sized to the ~44px minimum recommended by WCAG 2.5.5 /
   Apple & Material guidelines; form inputs kept at >=16px to stop
   iOS Safari's auto-zoom-on-focus. */

*, *::before, *::after {
  box-sizing: border-box;
}

/* Author stylesheet rules beat the browser's own [hidden]{display:none}
   user-agent rule regardless of selector specificity (origin outranks
   specificity in the cascade) - so any element this page also gives an
   explicit `display` (.field, .sub-fieldset, .actions-grid, etc. are all
   display:flex/grid) would silently ignore .hidden=true/the hidden
   attribute without this. Keep this rule first and !important so nothing
   added later can quietly reintroduce the same bug. */
[hidden] {
  display: none !important;
}

body {
  margin: 0;
  padding: 0;
  color: #000;
  background-color: #fff;
  font-family: "avant garde", "continuum light", futura, arial, helvetica, sans-serif;
  font-size: 16px;
  line-height: 1.4;
}

img {
  max-width: 100%;
  height: auto;
}

a { color: #0000ff; }
a:active { color: #000099; }
a:hover { color: #ff0000; }

h3 {
  font-weight: normal;
  font-family: "continuum medium", "avant garde", futura, arial, helvetica, sans-serif;
  font-size: 18px;
  margin: 0 0 8px;
}

.s8 { font-size: 12px; }

.page {
  --page-gutter: 16px;
  /* Shared by the archived template block AND the live-generated Summary
     output, so the two read consistently rather than one using this and
     the other silently falling back to the page's default sans-serif. */
  --readable-font: "Atkinson Hyperlegible", "avant garde", "continuum light", futura, arial, helvetica, sans-serif;
  max-width: 900px;
  margin: 0 auto;
  padding: 16px var(--page-gutter) 48px;
}

.site-header {
  text-align: center;
  margin-bottom: 16px;
}

.site-header .topbar {
  display: block;
  width: 100%;
  max-width: 576px;
  height: auto;
  margin: 0 auto;
}

.brand-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
}

.brand-row .dates {
  margin: 0;
  text-align: center;
  flex: 1 1 auto;
}

.intro {
  text-align: center;
  padding: 0 0 16px;
}

.intro p {
  margin: 8px 0;
}

/* ---------- form layout ---------- */

.ship-form {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.field-group {
  min-width: 0;
  border: 1px solid #ccc;
  border-radius: 8px;
  padding: 24px;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.field-group legend {
  font-weight: bold;
  /* Right-only: a symmetric 0 8px looked centered as a box, but the
     fieldset's own content already starts flush with the legend's box
     edge (verified: both sit at the same x-position) - left padding
     here would just push the legend's own text 8px further right than
     every field's own label text, undoing that alignment. */
  padding: 0 8px 0 0;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.field label {
  font-weight: bold;
}

.hint {
  font-size: 12px;
  color: #444;
  margin: 0;
}

.field-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.field-row .field {
  flex: 1 1 200px;
  min-width: 0;
}

.field--grow {
  flex: 2 1 260px;
}

#btnLowMass {
  width: auto;
  min-height: 44px;
  padding: 0 16px;
  font-size: 16px;
  font-weight: bold;
  border: 1px solid #888;
  border-radius: 8px;
  background-color: #f0f0f0;
}

/* For a pair that must always share one row (Mass Used/Mass Left) rather
   than wrap on narrow screens like every other .field-row pair here -
   a 0 basis lets both fields shrink to fit any width instead of wrapping
   once two 200px-basis fields plus the 16px gap no longer fit. */
.field-row--no-wrap {
  flex-wrap: nowrap;
}

.field-row--no-wrap .field {
  flex: 1 1 0;
}

/* The Auto button next to Mass - sized to its own label rather than
   growing to match Mass's width like the rule above, and pinned to
   the bottom of its column (flex-end) so it lines up with the Mass
   input, not the Mass label, above it. Same specificity as
   .field-row--no-wrap .field above (two classes each), so this has to
   come after it in source order to actually win - the slot-grid gap
   fix above already hit this exact "equal specificity, wrong order"
   trap once this session. */
.field-row--no-wrap .field--auto-fit {
  flex: 0 0 auto;
  justify-content: flex-end;
}

/* Each weapon/system slot's five fields, laid out by importance rather
   than left-to-right source order: System is what you're actually
   picking, so it gets its own full-width row; Number/Arcs and Ammo-Class/
   Bay are secondary pairs. A 6-column track lets the same markup produce
   a clean 50/50 split (3+3 tracks) on the narrow layout and a 50/50 +
   33/33/33 split (3+3, then 2+2+2 tracks) once there's room for three
   columns, without reordering the DOM or duplicating markup per
   breakpoint. */
.slot-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  grid-template-areas:
    "system system system system system system"
    "number number number arcs arcs arcs"
    "ammo ammo ammo bay bay bay";
  gap: 16px;
}

.slot-grid .field--system { grid-area: system; }
.slot-grid .field--number { grid-area: number; }
.slot-grid .field--arcs { grid-area: arcs; }
.slot-grid .field--ammo { grid-area: ammo; }
.slot-grid .field--bay { grid-area: bay; }

/* `gap` sizes the space between grid TRACKS as defined by
   grid-template-areas, regardless of whether a track's own cells are
   [hidden] - a fully-hidden row still gets a full 16px gap on each side
   of it, so the more trailing rows a slot hides (updateSlotFieldContext()
   hides Number/Arcs only when no System is chosen yet, and Ammo/Bay
   whenever the System doesn't use them), the more phantom empty space
   piles up below the last real field, on top of .sub-fieldset's own
   16px padding. Fixed by dropping the empty row(s) from the template
   entirely via :has() rather than just hiding their content, so the
   trailing space is always exactly the fieldset's own padding. Scoped
   to this breakpoint (mirroring the >=560px query below) since the two
   layouts group fields into different rows - an unscoped override here
   was winning at wide widths too (higher specificity than the plain
   .slot-grid rule inside the media query below), wrongly collapsing
   Class 3 Beam's row down to the narrow 2-row template even at 1024px -
   caught by measuring computed grid-template-areas directly rather than
   assuming the override only applied where intended. Number is hidden
   only when no System is chosen at all (see updateSlotFieldContext()),
   at which point Ammo/Bay are always hidden too - so checking Number
   alone fully identifies that case. */
@media (max-width: 559.98px) {
  .slot-grid:has(.field--number[hidden]) {
    grid-template-areas: "system system system system system system";
  }

  .slot-grid:has(.field--ammo[hidden]):has(.field--bay[hidden]):not(:has(.field--number[hidden])) {
    grid-template-areas:
      "system system system system system system"
      "number number number arcs arcs arcs";
  }
}

@media (min-width: 560px) {
  .slot-grid {
    grid-template-areas:
      "system system system number number number"
      "arcs arcs ammo ammo bay bay";
  }

  /* Same idea for this breakpoint's own row split - Arc/Ammo/Bay share
     one row here (Number moved up next to System), so it only needs
     collapsing when all three are hidden together. Number being hidden
     within the System/Number row doesn't leave a phantom row of its
     own - that's a same-row column gap, not a row gap - so it's not
     handled here. */
  .slot-grid:has(.field--arcs[hidden]):has(.field--ammo[hidden]):has(.field--bay[hidden]) {
    grid-template-areas: "system system system number number number";
  }
}

/* Inputs, selects & textareas: full width, touch-friendly height,
   >=16px text so mobile browsers don't zoom in on focus. */
input[type="text"],
input[type="email"],
select,
textarea {
  width: 100%;
  min-height: 44px;
  font-size: 16px;
  padding: 8px 10px;
  border: 1px solid #999;
  border-radius: 6px;
  background-color: #fff;
  font-family: inherit;
}

textarea {
  min-height: 88px;
  resize: vertical;
}

::placeholder {
  color: #ddd;
  opacity: 1;
}

/* Clearly distinct from an editable field (darker fill, muted ink) while
   keeping contrast high enough to stay legible (~10:1, well past WCAG AA). */
/* Selector specificity has to at least match input[type="text"] etc. above
   (element+attribute = 0,1,1) or these overrides silently lose regardless
   of source order - a bare .readOnly (0,1,0) never actually applied. */
input.readOnly,
textarea.readOnly {
  border-color: transparent;
  background-color: transparent;
  color: #333;
  font-weight: bold;
}

.error {
  color: #c00;
}

/* Error Notes (textarea) and Mass Left when negative (input, toggled in
   checkShip()) are both .readOnly and .error - the plain .readOnly rule
   above (0,1,1) otherwise beats a bare .error (0,1,0) regardless of
   source order, same specificity trap noted throughout this file, so
   these need to match or exceed it to actually win. */
input.readOnly.error,
textarea.readOnly.error {
  color: #c00;
}

/* Damage: total and the four quarters all on one line - "160 40/40/40/40" -
   matching how the FTSR text format and the original VBScript designer
   both show it, rather than spreading it across separate rows. Numbers
   only: at large hull sizes (100+ boxes per quarter on some official
   designs) a box-per-point visualization wraps across many lines and
   dominates the fieldset, so it doesn't scale - plain numbers do, at any
   hull size. */
/* nowrap + overflow-x so this genuinely always stays one line, matching
   the FTSR text format, even on the narrowest phone widths - it never
   drops the last quarter onto a second line the way a wrapping flex row
   would once the five boxes + separators stop fitting. */
.damage-track-row {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: 2px;
  overflow-x: auto;
}

/* Fixed rather than the usual full-width input: a few digits is all any of
   these five values ever needs (hull box counts don't realistically run
   past 3-4 digits). Centered, since each now sits inline against a "/" or
   its neighbor rather than under its own label - a left-aligned digit in
   a fixed-width box reads as off-center against that context.
   `input.damage-value` (not bare `.damage-value`) to match the specificity
   of `input[type="text"]` above - a bare class loses that tie regardless
   of source order and the width silently never applies (see the .readOnly
   fix above for the same bug class). Not a touch target (readonly,
   tabindex="-1"), so it doesn't need the 44px min-height every other
   input gets. */
input.damage-value {
  width: 2.5em;
  flex: 0 0 auto;
  text-align: center;
  min-height: 0;
  padding: 2px 4px;
}

/* Sets the total apart from the four-quarter breakdown that follows it. */
.damage-track-row input.damage-value:first-of-type {
  margin-right: 8px;
}

.damage-sep {
  font-weight: bold;
  color: #333;
}

/* A fixed grid rather than a wrapping flex row: each item's own input sits
   at a consistent column start regardless of how long its neighbor's label
   text is, so all four boxes line up top-to-bottom instead of drifting
   sideways depending on "Screens" vs "FCS" vs "ADFC" label width. */
.systems-inline {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px 24px;
}

.systems-inline-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: normal;
}

.systems-inline-item input {
  width: 4.5em;
  min-width: 56px;
}

/* The whole label is the tap target, not just the small checkbox glyph. */
.checkbox-field {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  font-weight: normal;
  /* Reads as a modifier on the System slots select right above it, not
     a section of its own, so it should sit closer to it than
     .ship-form's normal 24px between-section gap - pulled up to a net
     8px (24px gap - 16px) rather than restructuring the form around it. */
  margin-top: -16px;
}

.checkbox-field input {
  width: 20px;
  height: 20px;
  flex: 0 0 auto;
}

/* ---------- weapons/systems slots ---------- */
/* Each slot is its own top-level fieldset with real <label>s (reusing the
   same .field-row/.field pattern as the rest of the form, so a screen
   reader gets an actual accessible name for "Bay" or "Arcs", not decorative
   CSS text) - and no fieldset is nested inside another one; #slotsBody is a
   plain <div>, so these 15 fieldsets are its children, not descendants of
   some further wrapping fieldset. */

.section-heading {
  margin: 0;
  font-family: inherit;
  font-size: 16px;
  font-weight: bold;
}

.slots-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.sub-fieldset {
  min-width: 0;
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 16px;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.sub-fieldset legend {
  font-weight: bold;
  /* Right-only - see .field-group legend's own comment for why. */
  padding: 0 8px 0 0;
}

/* ---------- action buttons ---------- */

.actions-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
}

@media (min-width: 560px) {
  .actions-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

.actions-grid input {
  min-height: 48px;
  font-size: 16px;
  font-weight: bold;
  border: 1px solid #888;
  border-radius: 8px;
  background-color: #f0f0f0;
}

/* A lone button in its own row (Shrink Mass to Fit, Load Design, Load
   Example) - stays a full-width 1fr column always (same as it was via
   an inline style before), but on a wide screen a single button
   stretched across the whole 900px page reads as oversized for what
   it says. Capped to a third of the row's width and centered instead
   (per the user: a content-sized button "look[ed] arse"). Left
   full-width below 560px, same as every other button - only wide
   screens looked wrong. */
.actions-grid--solo {
  grid-template-columns: 1fr;
}

@media (min-width: 560px) {
  .actions-grid--solo input {
    width: 33%;
    justify-self: center;
  }
}

/* Flags Reset as the odd one out among these four - it discards the
   current design - rather than looking identical to the three that
   don't. Extra top margin sets it apart from the other three while
   they're stacked (below 560px); once the grid becomes a single row
   they're all cross-axis aligned already, so the margin would just
   shove Reset out of line with the rest of that row instead. */
#btnReset {
  border: 2px solid #c00;
  margin-top: 24px;
}

@media (min-width: 560px) {
  #btnReset {
    margin-top: 0;
  }
}

.actions-grid input:active {
  background-color: #ddd;
}

/* Standalone fieldsets/buttons sitting outside .ship-form's flex gap need
   their own margin to keep the same 24px fieldset-level rhythm. */
.page > .field-group,
.load-example-actions {
  margin-top: 24px;
}

/* ---------- output & template ---------- */

.output-panel {
  font-family: var(--readable-font);
  font-size: 16px;
  line-height: 1.7;
  border: 1px solid #ccc;
  border-radius: 8px;
  padding: 16px;
  margin-top: 24px;
  overflow-x: auto;
}

.output-panel table {
  width: 100%;
  border-collapse: collapse;
}

.template-heading {
  text-align: center;
  margin-top: 32px;
}

.template-block {
  font-family: var(--readable-font);
  font-size: 16px;
  line-height: 1.7;
  color: #111;
  white-space: pre-wrap;
  word-break: break-word;
  overflow-x: auto;
  background-color: #f6f6f4;
  border: 1px solid #ccc;
  border-radius: 8px;
  padding: 16px;
  /* Its own padding already insets the text, so it doesn't need the
     page's side gutter on top of that — let it run edge to edge. */
  margin-left: calc(-1 * var(--page-gutter));
  margin-right: calc(-1 * var(--page-gutter));
}
