/* Overhead Crane Budget Pricing Tool -- styles.
   Colors and type per the Han-Tek Brand Style Guide (same tokens used across
   Han-Tek's other internal tools):
   - Han-Tek Blue #003057 / Slate Blue Gray #384967 (background)
   - Han-Tek Orange #FFB549 (accents, CTAs -- never body text)
   - White body copy on dark backgrounds
   - Type stack: URW DIN (if licensed elsewhere) > DIN Pro > Roboto > system fallbacks

   Roboto is self-hosted (fonts/) rather than pulled from fonts.googleapis.com.
   The page is an internal tool reached over the LAN and, on Azure, from
   networks that may not allow arbitrary outbound requests -- a browser that
   can't reach Google's CDN was failing the stylesheet request outright
   (ERR_CONNECTION_REFUSED) instead of quietly falling back to a system font.
   Self-hosting also drops a third-party dependency from every page load.
   One variable-font file per subset, Latin only; the other subsets Google
   serves (Cyrillic, Greek, Vietnamese, math, symbols) aren't used here. */

@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('fonts/roboto-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('fonts/roboto-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --hantek-blue: #003057;
  --hantek-orange: #ffb549;
  --slate: #384967;
  --dark-gray: #1d252d;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { height: 100%; }

body {
  font-family: "URW DIN", "DIN Pro", "Roboto", Arial, "Helvetica Neue", sans-serif;
  color: #fff;
  background: radial-gradient(circle at 50% 0%, #1c3a5e 0%, var(--hantek-blue) 45%, var(--dark-gray) 100%);
  background-attachment: fixed;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
}

.topbar {
  padding: 1.5rem 1.5rem 1rem;
  text-align: center;
}
.wordmark { font-size: 1.1rem; font-weight: 700; letter-spacing: 0.02em; }
.wordmark .accent { color: var(--hantek-orange); }
.subtitle {
  display: block;
  margin-top: 0.3rem;
  font-size: 1.4rem;
  font-weight: 700;
}
.tagline {
  display: block;
  margin-top: 0.35rem;
  color: rgba(255, 255, 255, 0.6);
  font-size: 0.85rem;
}

/* Framed into han-tek.com (?embed=1 -- see _serve_page in api/server.py).
   That page already shows the wordmark's branding and an <h1> with the same
   text as .subtitle, so both are dropped here and only the disclaimer is
   kept. With the two larger lines gone the tagline is the first thing in the
   frame, so the topbar tightens up rather than leaving the gap they used to
   fill, and loses its own top margin so it reads as a caption on the host
   page's heading instead of a stranded line. */
.embedded .wordmark,
.embedded .subtitle { display: none; }
.embedded .topbar { padding: 0.9rem 1.5rem 0.4rem; }
.embedded .tagline { margin-top: 0; }

.layout {
  max-width: 72rem;
  margin: 0 auto;
  padding: 1rem 1.25rem 4rem;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 1.5rem;
  align-items: start;
}
@media (max-width: 900px) {
  .layout { grid-template-columns: 1fr; }
}

.panel {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 16px;
  padding: 1.5rem 1.5rem 1.75rem;
}

.panel h2 {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--hantek-orange);
  font-weight: 700;
  margin-bottom: 1rem;
}

.results-panel { position: sticky; top: 1rem; }

fieldset {
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 14px;
  padding: 1.1rem 1.25rem 1.25rem;
  margin-bottom: 1.25rem;
}
fieldset:last-of-type { margin-bottom: 0; }
legend {
  padding: 0 0.5rem;
  font-weight: 700;
  color: var(--hantek-orange);
  font-size: 0.9rem;
}

.field-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}
@media (max-width: 480px) {
  .field-grid { grid-template-columns: 1fr; }
}

label.field {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  font-size: 0.8rem;
  color: rgba(255, 255, 255, 0.65);
  margin-bottom: 1rem;
}
label.field:last-child { margin-bottom: 0; }

select, input[type="number"], input[type="email"], input[type="tel"] {
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 10px;
  padding: 0.6rem 0.75rem;
  color: #fff;
  font-size: 1rem;
  font-family: inherit;
  outline: 0;
  transition: border-color 0.2s;
  width: 100%;
}
select option { color: #000; }
/* Every control that takes the styling above also takes the focus ring.
   input[type="email"] was missing from this list while being present in the
   one above, so the email field has been quietly skipping the orange border
   on focus -- noticed while adding the phone field beside it. */
select:focus,
input[type="number"]:focus,
input[type="email"]:focus,
input[type="tel"]:focus { border-color: var(--hantek-orange); }

.hint {
  color: rgba(255, 255, 255, 0.4);
  font-size: 0.72rem;
}

/* Quieter than the label it sits inside, so "(optional)" reads as an aside
   and not as part of the field's name. */
.optional {
  color: rgba(255, 255, 255, 0.4);
  font-weight: 400;
}

.calc-status {
  min-height: 1.1rem;
  font-size: 0.8rem;
  color: rgba(255, 255, 255, 0.5);
  margin-top: 0.75rem;
}
.calc-status.error { color: #ff8a8a; }

/* --- results --- */
.spec-summary {
  color: rgba(255, 255, 255, 0.75);
  font-size: 0.95rem;
  line-height: 1.5;
  margin-bottom: 1.25rem;
  white-space: pre-line;
}

.sell-price-block {
  text-align: center;
  padding: 1.25rem 1rem 1.5rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  margin-bottom: 1.25rem;
}
.sell-price-label {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.55);
  margin-bottom: 0.4rem;
}
.sell-price-note {
  font-size: 1rem;
  color: rgba(255, 255, 255, 0.85);
  max-width: 32rem;
  margin: 0 auto;
}

.quote-form-block {
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  padding-top: 1.25rem;
}
.quote-form-block h2 {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--hantek-orange);
  font-weight: 700;
  margin-bottom: 1rem;
}
.quote-form-block form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.quote-form-block button {
  padding: 0.75rem 1.5rem;
  border-radius: 999px;
  border: 0;
  background: var(--hantek-orange);
  color: var(--hantek-blue);
  font-weight: 700;
  font-size: 1rem;
  cursor: pointer;
  transition: background 0.15s, transform 0.15s;
}
.quote-form-block button:hover:not(:disabled) { background: #ffc670; }
.quote-form-block button:active:not(:disabled) { transform: scale(0.97); }
.quote-form-block button:disabled { opacity: 0.6; cursor: default; }

/* Empty (0-height, no visual impact) whenever Turnstile isn't configured --
   see app.js. Cloudflare's widget renders itself into this container at a
   fixed size once loaded. */
.turnstile-widget:not(:empty) { max-width: 100%; overflow: hidden; }

.quote-status {
  min-height: 1.1rem;
  font-size: 0.8rem;
  color: rgba(255, 255, 255, 0.5);
}
.quote-status.error { color: #ff8a8a; }
.quote-status.success { color: #8fdf9f; }

.loading-overlay {
  opacity: 0.5;
  pointer-events: none;
  transition: opacity 0.15s;
}

/* --- crane diagram: a static background image (oc_form_image.png --
   already includes the illustration, logo, arrows, floor, and icons) with
   only the genuinely dynamic pieces overlaid on top: dimension text and the
   options checkmarks. Every overlay is absolutely positioned against
   .diagram-canvas, whose aspect-ratio matches the image so percentages stay
   correct at any width. Positions are fixed in index.html's inline styles
   image. Fixed in code -- the runtime editor was removed. --- */
.diagram-canvas {
  position: relative;
  width: 100%;
  aspect-ratio: 1.7152;
  background: #fff;
  border-radius: 12px;
  overflow: hidden;
  margin-bottom: 1.5rem;
  /* Lets child text be sized in cqw (% of THIS element's own width) instead
     of vw (% of the viewport) -- without this, label sizing only reacts to
     the browser window, not to how wide the diagram itself actually is
     (e.g. full-width section vs. the narrower results-panel column). */
  container-type: inline-size;
}

.diagram-bg {
  position: absolute;
  object-fit: contain;
}

.diagram-label {
  position: absolute;
  color: #c97a00;
  font-weight: 700;
  text-align: center;
  line-height: 1.15;
  font-size: clamp(0.5rem, 1.4cqw, 0.85rem);
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
}

/* The weight/capacity label sits on the dark hanging-weight icon in the
   image, where the orange fill (tuned for the light floor behind the other
   labels) loses contrast -- white with a dark shadow instead. */
.label-weight {
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}

.option-row {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
}

.opt-flag {
  font-size: clamp(0.65rem, 3.2cqw, 1rem);
  font-weight: 700;
}
.opt-flag-x { color: #d64545; }
.opt-flag-check { color: #2f9e52; }

/* frontend/admin.html -- reuses .layout/.panel/.field/.quote-status'
   patterns above rather than redefining them. */
.admin-layout {
  max-width: 40rem;
  margin: 0 auto;
  padding: 1rem 1.25rem 4rem;
}
.admin-note {
  font-size: 0.85rem;
  color: rgba(255, 255, 255, 0.65);
  margin-bottom: 1.25rem;
}
.admin-current {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  margin-bottom: 1.25rem;
  font-size: 1.1rem;
}
.admin-current strong { color: var(--hantek-orange); font-size: 1.4rem; }
#steelCostForm {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  margin-bottom: 2rem;
}
.admin-status {
  min-height: 1.1rem;
  font-size: 0.8rem;
  color: rgba(255, 255, 255, 0.5);
}
.admin-status.error { color: #ff8a8a; }
.admin-status.success { color: #8fdf9f; }
.admin-history {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}
.admin-history th, .admin-history td {
  text-align: left;
  padding: 0.4rem 0.6rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

/* --- admin: source workbook panel --- */
.workbook-current,
.workbook-previous {
  margin: 1rem 0;
}
.workbook-current h3,
.workbook-previous h3 {
  margin: 0 0 0.4rem;
  font-size: 0.9rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  opacity: 0.75;
}
/* Two columns so label/value pairs line up; a lone <dd> (the "no upload yet"
   fallback) spans both rather than sitting in a stray second column. */
.workbook-current dl,
.workbook-previous dl {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.25rem 0.9rem;
  margin: 0;
  font-size: 0.9rem;
}
.workbook-current dt,
.workbook-previous dt { opacity: 0.7; }
.workbook-current dd,
.workbook-previous dd { margin: 0; }
.workbook-current dd:only-child,
.workbook-previous dd:only-child { grid-column: 1 / -1; opacity: 0.7; }

.workbook-errors {
  margin: 0.6rem 0 0;
  padding-left: 1.1rem;
  font-size: 0.85rem;
  color: #d64545;
  max-height: 14rem;
  overflow-y: auto;
}
.workbook-errors li { margin-bottom: 0.2rem; }

/* --- contact block (bottom of the configuration form) ---
   Mirrors .quote-form-block's treatment on the results side -- rule above,
   small uppercase orange heading -- so the two panels end the same way. */
.contact-block {
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  margin-top: 1.25rem;
  padding-top: 1.25rem;
}
.contact-block h2 {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--hantek-orange);
  font-weight: 700;
  margin-bottom: 0.6rem;
}
.contact-intro {
  font-size: 0.8rem;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.65);
  margin-bottom: 0.9rem;
}
.contact-list { list-style: none; display: flex; flex-direction: column; gap: 0.5rem; }
.contact-list li { display: flex; align-items: baseline; gap: 0.6rem; }
.contact-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.45);
  flex: 0 0 3.2rem;
}
.contact-value {
  color: #fff;
  font-weight: 700;
  font-size: 1rem;
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 181, 73, 0.5);
  /* Long group addresses shouldn't widen the panel on a narrow screen. */
  overflow-wrap: anywhere;
}
.contact-value:hover,
.contact-value:focus-visible { color: var(--hantek-orange); border-bottom-color: var(--hantek-orange); }
