/* ==========================================================================
   StudentHPC — Components
   Every rule below reads semantic tokens only. No primitive (--pine-600,
   --slate-200) may appear in this file; if one is needed, add a semantic
   alias in tokens.css instead.
   Depends on: tokens.css, base.css
   ========================================================================== */

/* ==========================================================================
   BUTTONS
   Square-ish (3px), weight-carried, no gradient, no glow. Hover shifts the
   ground colour only -- no lift, no scale, no shadow bloom.
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  line-height: 1;
  letter-spacing: var(--ls-wide);
  padding: 0.75rem var(--sp-5);
  border: 1px solid transparent;
  border-radius: var(--r-2);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--motion-fast) var(--ease),
              border-color var(--motion-fast) var(--ease),
              color var(--motion-fast) var(--ease);
}
.btn:hover { text-decoration: none; }
.btn:disabled, .btn[aria-disabled='true'] { opacity: 0.5; cursor: not-allowed; }

.btn--primary {
  background: var(--surface-brand);
  color: var(--text-invert);
  border-color: var(--surface-brand);
}
.btn--primary:hover { background: var(--pine-700); border-color: var(--pine-700); color: var(--text-invert); }
.btn--primary:active { background: var(--pine-800); }

.btn--secondary {
  background: var(--surface);
  color: var(--text);
  border-color: var(--border-strong);
}
.btn--secondary:hover { background: var(--surface-subtle); border-color: var(--text-secondary); color: var(--text); }

.btn--invert {
  background: transparent;
  color: var(--text-invert);
  border-color: rgba(255, 255, 255, 0.35);
}
.btn--invert:hover { background: rgba(255, 255, 255, 0.10); border-color: var(--white); color: var(--text-invert); }

.btn--ghost { background: transparent; color: var(--text-link); border-color: transparent; padding-inline: var(--sp-3); }
.btn--ghost:hover { background: var(--blue-50); color: var(--text-link-hover); }

.btn--sm { font-size: var(--fs-xs); padding: 0.5rem var(--sp-3); }
.btn--lg { font-size: var(--fs-base); padding: 0.9375rem var(--sp-8); }
.btn--block { width: 100%; }

/* ==========================================================================
   BADGES & STATUS
   ========================================================================== */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-3xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  padding: 0.25rem var(--sp-2);
  border: 1px solid var(--border-base);
  border-radius: var(--r-1);
  background: var(--surface-subtle);
  color: var(--text-secondary);
  white-space: nowrap;
}
.badge--mono {
  font-family: var(--font-mono);
  text-transform: none;
  letter-spacing: var(--ls-normal);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-medium);
}
.badge--ok   { background: var(--status-ok-bg);   color: var(--status-ok-fg);   border-color: var(--status-ok-bd); }
.badge--warn { background: var(--status-warn-bg); color: var(--status-warn-fg); border-color: var(--status-warn-bd); }
.badge--err  { background: var(--status-err-bg);  color: var(--status-err-fg);  border-color: var(--status-err-bd); }
.badge--info { background: var(--status-info-bg); color: var(--status-info-fg); border-color: var(--status-info-bd); }
.badge--brand{ background: var(--pine-50); color: var(--text-brand); border-color: var(--pine-200); }

.status-dot {
  width: 8px; height: 8px;
  border-radius: var(--r-full);
  background: var(--status-ok-dot);
  flex-shrink: 0;
}
.badge--warn .status-dot { background: var(--status-warn-dot); }
.badge--err  .status-dot { background: var(--status-err-dot); }
.badge--info .status-dot { background: var(--status-info-dot); }

/* Live pulse. Purely additive: the dot is fully legible without it, and
   prefers-reduced-motion removes it via the global block in tokens.css. */
.status-dot--live { position: relative; }
.status-dot--live::after {
  content: '';
  position: absolute; inset: -3px;
  border-radius: var(--r-full);
  border: 1px solid currentColor;
  opacity: 0.5;
  animation: dot-pulse 2.4s ease-out infinite;
}
@keyframes dot-pulse {
  0%   { transform: scale(0.8); opacity: 0.55; }
  70%  { transform: scale(1.5); opacity: 0; }
  100% { transform: scale(1.5); opacity: 0; }
}

/* ==========================================================================
   CARDS
   Bordered, square-ish, flat. Depth comes from the border and a background
   step -- never from a shadow.
   ========================================================================== */
.card {
  background: var(--surface-raised);
  border: 1px solid var(--border-base);
  border-radius: var(--r-2);
  padding: var(--sp-6);
}
.card--flush { padding: 0; overflow: hidden; }
.card--subtle { background: var(--surface-subtle); }

/* Top accent rail — the one flourish, and it is a straight 3px edge. */
.card--railed { border-top: 3px solid var(--border-brand); }

.card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-5) var(--sp-6);
  border-bottom: 1px solid var(--border-hair);
  background: var(--surface-subtle);
}
.card__title { font-size: var(--fs-base); font-weight: var(--fw-semibold); letter-spacing: var(--ls-normal); }
.card__body { padding: var(--sp-6); }
.card__title-lg { font-size: var(--fs-xl); font-weight: var(--fw-semibold); }

.card-link {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: border-color var(--motion-fast) var(--ease), background-color var(--motion-fast) var(--ease);
}
.card-link:hover { border-color: var(--border-brand); background: var(--surface-inset); color: inherit; }
.card-link:hover .card__title { color: var(--text-brand); }

/* ==========================================================================
   SPEC LIST — label/value pairs, values always monospace
   The core "hardware" primitive. Used on cards and in the docs.
   ========================================================================== */
.spec-list { display: grid; gap: 0; }
.spec-list__row {
  display: grid;
  grid-template-columns: minmax(90px, 40%) 1fr;
  gap: var(--sp-4);
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--border-hair);
  align-items: baseline;
}
.spec-list__row:last-child { border-bottom: none; }
.spec-list__key {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--text-muted);
}
.spec-list__val {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--text);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

/* ==========================================================================
   STAT — a single figure with a caption
   ========================================================================== */
.stat { display: flex; flex-direction: column; gap: var(--sp-1); }
.stat__value {
  font-family: var(--font-mono);
  font-size: var(--fs-2xl);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--ls-display);
}
.stat__unit { font-size: var(--fs-base); font-weight: var(--fw-medium); color: var(--text-secondary); }
.stat__label {
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  font-weight: var(--fw-semibold);
  color: var(--text-muted);
}
.ground-invert .stat__label, .ground-brand .stat__label { color: var(--pine-200); }
.ground-invert .stat__unit,  .ground-brand .stat__unit  { color: var(--text-on-invert); }

/* ==========================================================================
   TABLES — dense, institutional, scrollable on narrow viewports
   ========================================================================== */
.table-scroll {
  overflow-x: auto;
  border: 1px solid var(--border-base);
  border-radius: var(--r-2);
  /* Focusable so keyboard users can scroll it; see JS for tabindex wiring. */
}
.table {
  width: 100%;
  font-size: var(--fs-sm);
  background: var(--surface);
}
.table th, .table td {
  padding: var(--sp-3) var(--sp-4);
  text-align: left;
  border-bottom: 1px solid var(--border-hair);
  vertical-align: top;
}
.table thead th {
  background: var(--surface-subtle);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--text-secondary);
  border-bottom: 1px solid var(--border-base);
  white-space: nowrap;
}
.table tbody tr:last-child td { border-bottom: none; }
.table tbody tr:hover { background: var(--surface-inset); }
.table code, .table .mono { font-size: var(--fs-2xs); }
.table--fixed { table-layout: fixed; }
.table caption {
  caption-side: bottom;
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-xs);
  color: var(--text-muted);
  text-align: left;
  border-top: 1px solid var(--border-hair);
}

/* ==========================================================================
   CODE
   ========================================================================== */

/* Inline — a chip, distinct from prose but not shouting. */
:not(pre) > code {
  font-size: 0.9em;
  padding: 0.125em 0.375em;
  background: var(--surface-inset);
  border: 1px solid var(--border-hair);
  border-radius: var(--r-1);
  color: var(--text);
  overflow-wrap: anywhere;
}
a > code { color: inherit; }

/* Block */
.code-block {
  background: var(--surface-code);
  border: 1px solid var(--slate-700);
  border-radius: var(--r-2);
  overflow: hidden;
  margin-block: var(--sp-5);
}
.code-block__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-2) var(--sp-3) var(--sp-2) var(--sp-4);
  background: var(--slate-800);
  border-bottom: 1px solid var(--slate-700);
}
.code-block__label {
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-medium);
  letter-spacing: var(--ls-wide);
  color: var(--slate-300);
  text-transform: none;
}
.code-block__file {
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  color: var(--syn-path);
}
.code-block__copy {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-medium);
  color: var(--slate-300);
  padding: 0.25rem var(--sp-2);
  border: 1px solid var(--slate-700);
  border-radius: var(--r-1);
  background: transparent;
  transition: color var(--motion-fast) var(--ease), border-color var(--motion-fast) var(--ease);
}
.code-block__copy:hover { color: var(--white); border-color: var(--slate-500); }
.code-block__copy[data-copied='true'] { color: var(--pine-300); border-color: var(--pine-400); }

.code-block pre {
  margin: 0;
  padding: var(--sp-4) var(--sp-5);
  overflow-x: auto;
  font-size: var(--fs-sm);
  line-height: var(--lh-code);
  color: var(--syn-text);
  tab-size: 2;
}
.code-block code { font-family: var(--font-mono); background: none; border: none; padding: 0; color: inherit; }

/* Syntax classes — applied by hand in markup. No highlighter dependency,
   no runtime JS, no 40 KB of grammar files for eight token types. */
.c-prompt  { color: var(--syn-prompt);  user-select: none; -webkit-user-select: none; }
.c-kw      { color: var(--syn-keyword); }
.c-str     { color: var(--syn-string); }
.c-num     { color: var(--syn-number); }
.c-cmt     { color: var(--syn-comment); font-style: italic; }
.c-path    { color: var(--syn-path); }
.c-dir     { color: var(--syn-keyword); font-weight: var(--fw-medium); }  /* #SBATCH directives */

/* Terminal variant — output lines sit muted beneath their command. */
.code-block--terminal .c-out { color: var(--slate-300); }

/* Line highlight, for calling out one directive in a longer script. */
.code-block .line-hl {
  display: inline-block;
  width: 100%;
  background: rgba(0, 118, 206, 0.14);
  box-shadow: inset 3px 0 0 var(--blue-500);
}

/* kbd */
kbd {
  font-family: var(--font-mono);
  font-size: 0.85em;
  padding: 0.1em 0.4em;
  background: var(--surface-subtle);
  border: 1px solid var(--border-base);
  border-bottom-width: 2px;
  border-radius: var(--r-1);
  color: var(--text);
  white-space: nowrap;
}

/* ==========================================================================
   CALLOUTS / ADMONITIONS  (ReadTheDocs lineage)
   Left rail + tinted wash. Type is carried by the label, never by colour
   alone -- required for WCAG 1.4.1 (use of colour).
   ========================================================================== */
.callout {
  border: 1px solid var(--border-base);
  border-left: 3px solid var(--border-strong);
  border-radius: var(--r-1);
  background: var(--surface-subtle);
  padding: var(--sp-4) var(--sp-5);
  margin-block: var(--sp-5);
  font-size: var(--fs-base);
}
.callout__label {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  margin-bottom: var(--sp-2);
  color: var(--text-secondary);
}
.callout p + p { margin-top: var(--sp-3); }
.callout > :last-child { margin-bottom: 0; }

.callout--note    { background: var(--status-info-bg); border-color: var(--status-info-bd); border-left-color: var(--status-info-dot); }
.callout--note    .callout__label { color: var(--status-info-fg); }
.callout--tip     { background: var(--status-ok-bg);   border-color: var(--status-ok-bd);   border-left-color: var(--status-ok-dot); }
.callout--tip     .callout__label { color: var(--status-ok-fg); }
.callout--warning { background: var(--status-warn-bg); border-color: var(--status-warn-bd); border-left-color: var(--status-warn-dot); }
.callout--warning .callout__label { color: var(--status-warn-fg); }
.callout--danger  { background: var(--status-err-bg);  border-color: var(--status-err-bd);  border-left-color: var(--status-err-dot); }
.callout--danger  .callout__label { color: var(--status-err-fg); }

/* ==========================================================================
   BREADCRUMBS
   ========================================================================== */
.breadcrumb { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); font-size: var(--fs-xs); color: var(--text-muted); }
.breadcrumb a { color: var(--text-secondary); text-decoration: none; }
.breadcrumb a:hover { color: var(--text-link); text-decoration: underline; }
.breadcrumb__sep { color: var(--border-strong); user-select: none; }
.breadcrumb [aria-current='page'] { color: var(--text); font-weight: var(--fw-medium); }

/* ==========================================================================
   FORMS
   ========================================================================== */
.field { display: flex; flex-direction: column; gap: var(--sp-2); }

.field__label {
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--text);
}
.field__req { color: var(--status-err-fg); margin-left: 2px; }
.field__hint { font-size: var(--fs-xs); font-weight: var(--fw-regular); color: var(--text-muted); display: block; margin-top: 2px; }

.input, .textarea, .select {
  width: 100%;
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-1);
  padding: 0.625rem var(--sp-3);
  transition: border-color var(--motion-fast) var(--ease), box-shadow var(--motion-fast) var(--ease);
}
.input::placeholder, .textarea::placeholder { color: var(--text-muted); }
.input:hover, .textarea:hover, .select:hover { border-color: var(--text-muted); }
.input:focus, .textarea:focus, .select:focus {
  outline: none;
  border-color: var(--border-focus);
  box-shadow: 0 0 0 3px var(--blue-100);
}
.input--mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.textarea { min-height: 9rem; resize: vertical; line-height: var(--lh-normal); }

.select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%23566270' stroke-width='1.75' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--sp-3) center;
  padding-right: var(--sp-8);
}

.field--invalid .input, .field--invalid .textarea, .field--invalid .select { border-color: var(--status-err-dot); }
.field--invalid .input:focus, .field--invalid .textarea:focus { box-shadow: 0 0 0 3px var(--status-err-bg); }

.field__error {
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  color: var(--status-err-fg);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}
.field__error:empty { display: none; }

.field__foot { display: flex; justify-content: space-between; gap: var(--sp-3); align-items: flex-start; }
.char-count { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-muted); font-variant-numeric: tabular-nums; flex-shrink: 0; }
.char-count--near { color: var(--status-warn-fg); }
.char-count--at   { color: var(--status-err-fg); }

.fieldset { border: none; }
.fieldset + .fieldset { margin-top: var(--sp-10); padding-top: var(--sp-8); border-top: 1px solid var(--border-hair); }
.fieldset__legend {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-size: var(--fs-lg);
  font-weight: var(--fw-semibold);
  margin-bottom: var(--sp-5);
  width: 100%;
}
.fieldset__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px; height: 26px;
  background: var(--surface-brand);
  color: var(--text-invert);
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  border-radius: var(--r-1);
  flex-shrink: 0;
}
.fieldset__optional { font-size: var(--fs-sm); font-weight: var(--fw-regular); color: var(--text-muted); }

.form-grid { display: grid; gap: var(--sp-5); }
.form-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.form-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* Honeypot — off-screen, never focusable, never announced. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; opacity: 0; pointer-events: none; }

/* Upload */
.upload {
  position: relative;
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-2);
  background: var(--surface-inset);
  transition: border-color var(--motion-fast) var(--ease), background-color var(--motion-fast) var(--ease);
}
.upload:hover, .upload.is-dragover { border-color: var(--border-brand); background: var(--pine-50); }
.upload__input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.upload__ui { display: flex; flex-direction: column; align-items: center; gap: var(--sp-2); padding: var(--sp-8) var(--sp-5); text-align: center; pointer-events: none; }
.upload__text { font-size: var(--fs-sm); color: var(--text-secondary); }
.upload__browse { color: var(--text-link); font-weight: var(--fw-semibold); text-decoration: underline; }
.upload__file { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-muted); }
.upload__file.has-file { color: var(--status-ok-fg); font-weight: var(--fw-medium); }

/* Form-level status banner */
.form-status {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border: 1px solid;
  border-radius: var(--r-2);
  font-size: var(--fs-sm);
  margin-bottom: var(--sp-6);
}
.form-status--ok  { background: var(--status-ok-bg);  color: var(--status-ok-fg);  border-color: var(--status-ok-bd); }
.form-status--err { background: var(--status-err-bg); color: var(--status-err-fg); border-color: var(--status-err-bd); }

/* Spinner */
.spinner {
  width: 14px; height: 14px;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: var(--white);
  border-radius: var(--r-full);
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

@media (max-width: 768px) {
  .form-grid--2, .form-grid--3 { grid-template-columns: minmax(0, 1fr); }
}

/* --- Badge on a dark panel ------------------------------------------- */
.badge--invert {
  background: transparent;
  border-color: var(--border-invert);
  color: var(--syn-path);
}

/* ==========================================================================
   DENY LIST — things explicitly out of scope.
   Marked with a rule and an em dash rather than a checkmark, so it cannot be
   mistaken for the eligibility checklist it sits beside.
   ========================================================================== */
.denylist { display: flex; flex-direction: column; gap: 0; }
.denylist__item {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--sp-3);
  align-items: baseline;
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--border-hair);
  font-size: var(--fs-sm);
  color: var(--text-secondary);
}
.denylist__item:last-child { border-bottom: none; }
.denylist__mark {
  font-family: var(--font-mono);
  color: var(--status-err-fg);
  font-weight: var(--fw-bold);
  line-height: 1;
  user-select: none;
}

/* Card supporting text */
.card__intro {
  font-size: var(--fs-sm);
  line-height: var(--lh-relaxed);
  color: var(--text-secondary);
  margin-bottom: var(--sp-5);
}
.card__footnote {
  font-size: var(--fs-xs);
  color: var(--text-muted);
  margin-top: var(--sp-5);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--border-hair);
}

/* Upload icon + small-print utility used by the application form */
.upload__icon { color: var(--text-muted); }
.upload:hover .upload__icon { color: var(--text-brand); }
.fs-xs { font-size: var(--fs-xs); }

/* ==========================================================================
   ERROR PAGES
   Deliberately plain: one code, one sentence, one way to get help. An error
   page that tries to be clever wastes the reader's time at the exact moment
   they have least patience for it.
   ========================================================================== */
.errpage {
  min-height: 70vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding-block: var(--sp-16);
}
.errpage__inner { max-width: 56ch; }
.errpage__code {
  font-family: var(--font-mono);
  font-size: var(--fs-3xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--text-muted);
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  border: 1px solid var(--border-base);
  border-radius: var(--r-1);
  padding: var(--sp-2) var(--sp-3);
  margin-bottom: var(--sp-6);
}
.errpage__title {
  font-size: var(--fs-4xl);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-display);
  line-height: var(--lh-tight);
  margin-bottom: var(--sp-5);
}
.errpage__body {
  font-size: var(--fs-lg);
  line-height: var(--lh-relaxed);
  color: var(--text-secondary);
  margin-bottom: var(--sp-8);
}
.errpage__actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-bottom: var(--sp-8); }
.errpage__contact {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--border-hair);
  font-style: normal;   /* <address> defaults to italic */
}

.legal-contact { font-style: normal; color: var(--text-secondary); }

@media (max-width: 480px) {
}
