/* ============================================================
   Europass CV Generator — Design System
   Hand-written CSS with custom properties. No frameworks.

   Rebrand note: this product is positioned as a sub-tool of collabwith
   (https://collabwith.com/). Tokens below are DERIVED from the live site,
   not invented:
     --cw-ink   #0d0d0d  ← --nv-primary-accent   (collabwith's primary button /
                                                    dark-surface colour)
     --cw-lime  #d6fe51  ← --nv-c-1 / --secondarybtnbg (their signature accent)
     --cw-lime-strong #96f702 ← --hovercolor (their own hover state for the
                                                accent, found paired with the
                                                dark-surface tokens below)
     --cw-cream #e9e2d8  ← --nv-c-2 / --nv-light-bg (warm neutral surface)
     dark mode bg/text: #121212 / #fafafa ← --nv-dark-bg / --color
     font: Lato (400/700), incl. weight 900 for display ← --bodyfontfamily /
                                                            --headingsfontfamily
     radius: sharpened toward their literal 3px button radius.
   See CLAUDE.md / handoff notes for the full derivation record.
   ============================================================ */

/* ── Brand primitives (rarely referenced directly — prefer the semantic
       tokens below) ──────────────────────────────────────────────────────── */
:root {
  --cw-ink:          #0d0d0d;
  --cw-lime:         #d6fe51;
  --cw-lime-strong:  #96f702;
  --cw-cream:        #e9e2d8;
}

/* ── Design tokens (semantic — light theme, default) ──────────────────── */
:root {
  --accent:          var(--cw-ink);
  --accent-hover:    #262626;
  --accent-light:    #f5f8dc;               /* pale lime-cream wash */
  --accent-ring:     rgba(214, 254, 81, .55); /* lime focus glow — the signature detail */
  /* Foreground colour to paint on top of a solid --accent fill. Kept as its
     own token (rather than a hardcoded #fff) because dark mode flips --accent
     to lime, which needs dark text, not white — see the dark-mode block. */
  --accent-on:       #ffffff;

  --bg:              #faf9f5;
  --surface:         #ffffff;
  --border:          #e6e4dd;
  --border-subtle:   #f0efe9;
  --border-strong:   #d4d2c9;
  --border-focus:    var(--accent);
  --surface-hover:   #f3f4f0;
  --code-bg:         #f8f9fc;

  --text:            #171716;
  --text-secondary:  #6b6963;
  --text-muted:      #9c9990;

  --success:         #059669;
  --success-bg:      #ecfdf5;
  --success-border:  #a7f3d0;

  --error:           #dc2626;
  --error-bg:        #fef2f2;
  --error-border:    #fecaca;

  --warn:            #d97706;
  --warn-bg:         #fffbeb;

  --info:            #1d4ed8;
  --info-bg:         #eff6ff;

  --radius:          10px;
  --radius-md:       14px;
  --radius-sm:       6px;
  --radius-xs:       3px;

  --shadow-sm:       0 1px 2px rgba(0, 0, 0, .05);
  --shadow:          0 1px 3px rgba(0, 0, 0, .07), 0 6px 20px rgba(0, 0, 0, .06);
  --shadow-lg:       0 4px 6px rgba(0, 0, 0, .07), 0 16px 48px rgba(0, 0, 0, .08);

  --font:            "Lato", -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono:       "SF Mono", "Fira Code", "Cascadia Code", "Consolas", monospace;

  --transition:      150ms ease;
}

/* ── Dark theme ─────────────────────────────────────────────────────────
   Also derived from collabwith's own CSS custom properties, not invented:
   the trio --bgcolor:#0d0d0d / --color:#fafafa / --hovercolor:#96f702 appears
   together in their stylesheet as a dark-surface colour scheme. */
@media (prefers-color-scheme: dark) {
  :root {
    --accent:          var(--cw-lime);
    --accent-hover:    var(--cw-lime-strong);
    --accent-light:    rgba(214, 254, 81, .12);
    --accent-ring:     rgba(214, 254, 81, .4);
    --accent-on:       var(--cw-ink);

    --bg:              #121212;
    --surface:         #1b1b19;
    --border:          #302f2b;
    --border-subtle:   #262622;
    --border-strong:   #3d3c36;
    --border-focus:    var(--accent);
    --surface-hover:   #232320;
    --code-bg:         #1a1a17;

    --text:            #fafafa;
    --text-secondary:  #b6b3ab;
    --text-muted:      #837f75;

    --success:         #34d399;
    --success-bg:      rgba(52, 211, 153, .1);
    --success-border:  rgba(52, 211, 153, .3);

    --error:           #f87171;
    --error-bg:        rgba(248, 113, 113, .1);
    --error-border:    rgba(248, 113, 113, .3);

    --warn:            #fbbf24;
    --warn-bg:         rgba(251, 191, 36, .1);

    --info:            #60a5fa;
    --info-bg:         rgba(96, 165, 250, .12);

    --shadow-sm:       0 1px 2px rgba(0, 0, 0, .4);
    --shadow:          0 1px 3px rgba(0, 0, 0, .5), 0 6px 20px rgba(0, 0, 0, .35);
    --shadow-lg:       0 4px 6px rgba(0, 0, 0, .5), 0 16px 48px rgba(0, 0, 0, .4);
  }

  /* .btn-primary already reads color: var(--accent-on) at its base rule, so
     it adapts automatically (lime fill + ink text in dark mode — the same
     pairing collabwith uses for its own dark-surface accent). review.html's
     .entry-index gets the equivalent fix inline, since that rule lives in
     the page's own <style> block and would otherwise win the cascade tie.
     Everything else that differs between themes (hover washes, subtle
     borders, code backgrounds) is carried by the --surface-hover /
     --border-subtle / --border-strong / --code-bg tokens above, so no
     further per-selector overrides are needed here. */
}

/* ── Reset & base ──────────────────────────────────────────────────────── */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Without this, iOS Safari inflates body text on rotation into landscape — a layout
     that fits in portrait then reflows and overflows. Pinning to 100% keeps the author's
     sizes and does NOT override the reader's own accessibility text scaling. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  font-family: var(--font);
  font-size: 0.9375rem;  /* 15px */
  line-height: 1.6;
  color: var(--text);
  background: var(--bg);
  min-height: 100vh;
  min-height: 100dvh;   /* dvh excludes the collapsing mobile URL bar; vh above is the fallback */
}

a {
  color: var(--accent);
  text-decoration: none;
  transition: color var(--transition);
}
a:hover {
  color: var(--accent-hover);
  text-decoration: underline;
}
a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}

h1, h2, h3 {
  font-weight: 600;
  line-height: 1.25;
  color: var(--text);
}

code {
  font-family: var(--font-mono);
  font-size: 0.875em;
  background: var(--surface-hover);
  padding: 0.1em 0.35em;
  border-radius: var(--radius-xs);
  color: var(--text);
}

/* ── Layout ────────────────────────────────────────────────────────────── */
.page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;   /* dvh excludes the collapsing mobile URL bar; vh above is the fallback */
}

.main {
  flex: 1;
  padding: 2rem 1rem 4rem;
}

.container {
  max-width: 1100px;
  margin: 0 auto;
}

/* ── Navigation ─────────────────────────────────────────────────────────
   Deliberately a fixed near-black bar in BOTH light and dark site themes
   (not theme-driven var(--surface)) — this is what makes every authenticated
   screen read as "a collabwith product" at a glance, matching the ink/lime
   pairing collabwith uses for its own dark surfaces. */
.nav {
  background: var(--cw-ink);
  border-bottom: 1px solid rgba(255, 255, 255, .08);
  position: sticky;
  top: 0;
  z-index: 100;
  box-shadow: var(--shadow-sm);
}

.nav-inner {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 1rem;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.nav-brand {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  text-decoration: none;
}
.nav-brand:hover {
  text-decoration: none;
}
.nav-brand:hover .nav-brand-product {
  color: var(--cw-lime);
}
.nav-brand:focus-visible {
  outline: 2px solid var(--cw-lime);
  outline-offset: 3px;
  border-radius: var(--radius-xs);
}

.nav-brand-mark {
  display: block;
  width: 28px;
  height: 28px;
  border-radius: 7px;
  flex-shrink: 0;
}

/* Two-line lockup: the collabwith family name sits as a small eyebrow above
   the actual product name, so "Europass CV Generator" stays the headline
   identity on every page — see task requirement for a clear product name. */
.nav-brand-lockup {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}
.nav-brand-eyebrow {
  font-size: 0.625rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--cw-lime);
}
.nav-brand-product {
  font-size: 0.9375rem;
  font-weight: 700;
  color: #ffffff;
  letter-spacing: -0.01em;
  transition: color var(--transition);
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

.nav-link {
  padding: 0.375rem 0.75rem;
  border-radius: var(--radius-sm);
  font-size: 0.875rem;
  font-weight: 500;
  color: rgba(255, 255, 255, .72);
  text-decoration: none;
  transition: color var(--transition), background var(--transition);
}
.nav-link:hover {
  color: #ffffff;
  background: rgba(255, 255, 255, .1);
  text-decoration: none;
}
.nav-link:focus-visible {
  outline: 2px solid var(--cw-lime);
  outline-offset: 2px;
}

.nav-logout-form {
  margin-left: 0.25rem;
}

/*
  Signed-in account, shown left of "Sign out". Truncates rather than wrapping: an
  email is unbounded input and must not be allowed to reflow the nav bar.
*/
.nav-user {
  color: rgba(255, 255, 255, .62);
  font-size: .8125rem;
  margin-left: .75rem;
  max-width: 15rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
@media (max-width: 640px) {
  /* The nav is cramped on phones and "Sign out" is the actionable half of the pair. */
  .nav-user { display: none; }
}

/*
  Given a visible border. As a bare ghost button this read as body text against the
  dark nav and users did not find it -- the control existed but was not an affordance.
*/
.nav-signout {
  color: rgba(255, 255, 255, .85);
  border: 1px solid rgba(255, 255, 255, .32);
  border-radius: 6px;
}
.nav-signout:hover {
  color: #ffffff;
  background: rgba(255, 255, 255, .14);
  border-color: rgba(255, 255, 255, .55);
}
.nav-signout:focus-visible {
  outline: 2px solid var(--cw-lime);
  outline-offset: 2px;
}

/* ── Checkbox row ("Keep me signed in" on login.html) ──────────────────── */
.form-check {
  display: flex;
  align-items: center;
  gap: .5rem;
  margin: -.25rem 0 1rem;
}
.form-check-input {
  width: 1rem;
  height: 1rem;
  margin: 0;
  flex: 0 0 auto;
  accent-color: var(--accent);
  cursor: pointer;
}
.form-check-label {
  font-size: .875rem;
  color: var(--text-secondary);
  cursor: pointer;
  user-select: none;
}

/* ── Page header ───────────────────────────────────────────────────────── */
.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  margin-bottom: 1.75rem;
}

.page-title {
  font-size: 1.625rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text);
}

.page-subtitle {
  margin-top: 0.375rem;
  color: var(--text-secondary);
  font-size: 0.9375rem;
}

/* ── Cards ─────────────────────────────────────────────────────────────── */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.75rem;
  box-shadow: var(--shadow);
  margin-bottom: 1.5rem;
}

.card-title {
  font-size: 1.0625rem;
  font-weight: 600;
  margin-bottom: 0.375rem;
  letter-spacing: -0.01em;
}

.card-subtitle {
  color: var(--text-secondary);
  font-size: 0.875rem;
  margin-bottom: 1.25rem;
  line-height: 1.5;
}

.card-footer-note {
  margin-top: 1rem;
  font-size: 0.875rem;
  color: var(--text-secondary);
}

/* ── Buttons ───────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 1.125rem;
  border-radius: var(--radius-sm);
  font-family: var(--font);
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.4;
  cursor: pointer;
  border: 1px solid transparent;
  text-decoration: none;
  transition: background var(--transition), color var(--transition),
              border-color var(--transition), box-shadow var(--transition);
  white-space: nowrap;
}
.btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.btn-primary {
  background: var(--accent);
  color: var(--accent-on);
  border-color: var(--accent);
}
.btn-primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  color: var(--accent-on);
  text-decoration: none;
  /* Lime glow on hover — the one micro-interaction that shows up on every
     primary action in the app, regardless of theme. */
  box-shadow: 0 4px 16px rgba(214, 254, 81, .45);
}

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

.btn-ghost {
  background: transparent;
  color: var(--text-secondary);
  border-color: transparent;
}
.btn-ghost:hover {
  background: var(--surface-hover);
  color: var(--text);
  text-decoration: none;
}

.btn-sm {
  padding: 0.3rem 0.75rem;
  font-size: 0.8125rem;
}

.btn-full {
  width: 100%;
  justify-content: center;
}

.btn-download {
  font-size: 0.9375rem;
  padding: 0.625rem 1.5rem;
}

/* ── Forms ─────────────────────────────────────────────────────────────── */
.form-group {
  margin-bottom: 1.25rem;
}

.form-label {
  display: block;
  font-size: 0.875rem;
  font-weight: 500;
  margin-bottom: 0.4rem;
  color: var(--text);
}

.form-hint {
  font-weight: 400;
  color: var(--text-muted);
  font-size: 0.8125rem;
  margin-left: 0.25rem;
}

.form-input {
  display: block;
  width: 100%;
  padding: 0.5rem 0.75rem;
  font-family: var(--font);
  font-size: 0.9375rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  line-height: 1.5;
  transition: border-color var(--transition), box-shadow var(--transition);
  appearance: none;
}
.form-input:focus {
  outline: none;
  border-color: var(--border-focus);
  box-shadow: 0 0 0 3px var(--accent-ring);
}
.form-input::placeholder {
  color: var(--text-muted);
}

.form-input-file {
  padding: 0.375rem 0.75rem;
  cursor: pointer;
}
.form-input-file::file-selector-button {
  padding: 0.25rem 0.625rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-xs);
  background: var(--surface-hover);
  font-size: 0.8125rem;
  cursor: pointer;
  margin-right: 0.5rem;
  transition: background var(--transition);
}
.form-input-file::file-selector-button:hover {
  background: var(--border-subtle);
}

.form-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%236b7280' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.75rem center;
  padding-right: 2.25rem;
  cursor: pointer;
}

.form-textarea {
  resize: vertical;
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  min-height: 100px;
}

.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}
@media (max-width: 600px) {
  .form-row {
    grid-template-columns: 1fr;
  }
}

/* ── Advanced toggle ───────────────────────────────────────────────────── */
.upload-actions {
  margin-top: 1.5rem;
  display: flex;
  gap: 0.75rem;
}

/* ── Upload card ───────────────────────────────────────────────────────── */
.upload-card {
  border-left: 4px solid var(--accent);
}

/* ── Alerts ────────────────────────────────────────────────────────────── */
.alert {
  display: flex;
  align-items: flex-start;
  gap: 0.625rem;
  padding: 0.75rem 1rem;
  border-radius: var(--radius-sm);
  font-size: 0.875rem;
  margin-bottom: 1.25rem;
  line-height: 1.5;
}

.alert-icon {
  flex-shrink: 0;
  margin-top: 0.1em;
}

.alert-error {
  background: var(--error-bg);
  border: 1px solid var(--error-border);
  color: var(--error);
}

.alert-success {
  background: var(--success-bg);
  border: 1px solid var(--success-border);
  color: var(--success);
}

/* ── Status badges ─────────────────────────────────────────────────────── */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 0.2em 0.7em;
  border-radius: 100px;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  white-space: nowrap;
  background: var(--surface-hover);
  color: var(--text-secondary);
}

.badge-lg {
  font-size: 0.875rem;
  padding: 0.35em 1em;
}

.badge-queued {
  background: var(--surface-hover);
  color: var(--text-secondary);
}

.badge-processing {
  background: var(--info-bg);
  color: var(--info);
}

.badge-completed {
  background: var(--success-bg);
  color: var(--success);
}

.badge-failed {
  background: var(--error-bg);
  color: var(--error);
}

.badge-free {
  background: var(--surface-hover);
  color: var(--text-secondary);
}

.badge-pro {
  background: var(--accent-light);
  color: var(--accent);
}

/* ── Account status (dashboard page-header) ───────────────────────────── */
.account-status {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  flex-wrap: wrap;
  padding-top: 0.125rem;
}

.account-status-detail {
  font-size: 0.875rem;
  color: var(--text-secondary);
}

/* ── Table ─────────────────────────────────────────────────────────────── */
.table-wrapper {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin: 0 -0.25rem;
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}

.table th {
  text-align: left;
  padding: 0.625rem 0.75rem;
  font-weight: 600;
  font-size: 0.8125rem;
  color: var(--text-secondary);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.table td {
  padding: 0.75rem 0.75rem;
  border-bottom: 1px solid var(--border-subtle);
  vertical-align: middle;
}

.table tbody tr:last-child td {
  border-bottom: none;
}

.table tbody tr:hover td {
  background: var(--surface-hover);
}

.job-id-cell {
  color: var(--text-secondary);
}

.action-cell {
  text-align: right;
}

.link-action {
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--accent);
}

/* ── Monospace ─────────────────────────────────────────────────────────── */
.monospace {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
}

/* ── Empty state ───────────────────────────────────────────────────────── */
.empty-state {
  padding: 2.5rem 1rem;
  text-align: center;
}

.empty-state-text {
  color: var(--text-secondary);
  font-size: 0.9375rem;
}

/* ── Text helpers ──────────────────────────────────────────────────────── */
.text-secondary {
  color: var(--text-secondary);
}

/* ── Job detail — status card ──────────────────────────────────────────── */
.status-card {
  border-left: 4px solid var(--accent);
}

.status-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.5rem;
  flex-wrap: wrap;
}

.meta-list {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.5rem 1.5rem;
  font-size: 0.875rem;
  list-style: none;
  margin-bottom: 1.5rem;
}

.meta-list dt {
  color: var(--text-secondary);
  font-weight: 500;
  white-space: nowrap;
}

.meta-list dd {
  color: var(--text);
  word-break: break-all;
}

/* ── Progress indicator ────────────────────────────────────────────────── */
.progress-indicator {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  color: var(--text-secondary);
  font-size: 0.875rem;
  margin-top: 0.5rem;
}

.spinner {
  display: inline-block;
  width: 16px;
  height: 16px;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
  flex-shrink: 0;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* ── Warnings ──────────────────────────────────────────────────────────── */
.warnings-section {
  margin-top: 1.25rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--border);
}

.warnings-title {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--warn);
  margin-bottom: 0.5rem;
}

.warnings-list {
  padding-left: 1.25rem;
  font-size: 0.875rem;
  color: var(--text-secondary);
  line-height: 1.6;
}

/* ── Download card ─────────────────────────────────────────────────────── */
.download-card {
  border-left: 4px solid var(--success);
}

.download-actions {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-top: 0.5rem;
}

/* ── Error card ────────────────────────────────────────────────────────── */
.error-card {
  border-left: 4px solid var(--error);
}

.error-text {
  color: var(--text-secondary);
  font-size: 0.9375rem;
  margin-bottom: 1.25rem;
  line-height: 1.6;
}

/* ── Breadcrumb ────────────────────────────────────────────────────────── */
.breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.875rem;
  color: var(--text-secondary);
  margin-bottom: 1.25rem;
}

.breadcrumb-link {
  color: var(--accent);
}

.breadcrumb-sep {
  color: var(--text-muted);
}

.breadcrumb-current {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  color: var(--text-secondary);
}

/* ── Code blocks (api-access) ──────────────────────────────────────────── */
.code-block-wrapper {
  position: relative;
  margin-top: 0.5rem;
  margin-bottom: 0.25rem;
}

.code-block {
  display: block;
  background: var(--code-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.875rem 4rem 0.875rem 1rem;  /* right padding for copy button */
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  line-height: 1.7;
  color: var(--text);
  overflow-x: auto;
  white-space: pre;
  word-break: normal;
}

.code-block-pre {
  padding: 1rem 4rem 1rem 1rem;
}
.code-block-pre code {
  background: none;
  padding: 0;
  font-size: inherit;
}

.copy-btn {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  border: 1px solid var(--border);
  background: var(--surface);
}
.copy-btn:hover {
  background: var(--accent-light);
  color: var(--accent);
  border-color: var(--accent);
}

/* ── curl samples ──────────────────────────────────────────────────────── */
.curl-sample {
  margin-bottom: 2rem;
}
.curl-sample:last-child {
  margin-bottom: 0;
}

.curl-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.875rem;
  font-weight: 600;
  margin-bottom: 0.375rem;
  color: var(--text);
}

.curl-method {
  display: inline-flex;
  align-items: center;
  padding: 0.1em 0.5em;
  border-radius: var(--radius-xs);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  font-family: var(--font-mono);
}

.curl-method.post {
  background: var(--warn-bg);
  color: var(--warn);
}

.curl-method.get {
  background: var(--accent-light);
  color: var(--accent);
}

.curl-note {
  margin-top: 0.5rem;
  font-size: 0.8125rem;
  color: var(--text-secondary);
  line-height: 1.5;
}

/* ── Login page ────────────────────────────────────────────────────────── */
.login-page {
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  min-height: 100dvh;   /* dvh excludes the collapsing mobile URL bar; vh above is the fallback */
  padding: 2rem 1rem;
}

.login-main {
  width: 100%;
  max-width: 420px;
}

.login-card {
  padding: 2.5rem 2rem;
}

.login-header {
  text-align: center;
  margin-bottom: 2rem;
}

.login-icon-mark {
  display: inline-block;
  border-radius: 8px;
  margin-bottom: 0.75rem;
}

.login-title {
  font-size: 1.375rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin-bottom: 0.25rem;
}

.login-subtitle {
  font-size: 0.875rem;
  color: var(--text-secondary);
}

.login-form {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.login-footer-link {
  margin-top: 1.5rem;
  text-align: center;
  font-size: 0.875rem;
  color: var(--text-secondary);
}

/* ── Landing page (login.html) ─────────────────────────────────────────────
   GET "/" always redirects through to this exact route for a logged-out
   visitor (see the comment at the top of login.html), so this is the page
   that has to explain the product and carry the collabwith identity — the
   marketing pane is deliberately always near-black, matching the nav bar and
   collabwith's own primary-button/dark-surface colour, regardless of the
   viewer's light/dark preference. The auth pane stays theme-aware like the
   rest of the app. */
.landing-page {
  min-height: 100vh;
  min-height: 100dvh;   /* dvh excludes the collapsing mobile URL bar; vh above is the fallback */
  display: grid;
  grid-template-columns: minmax(0, 1fr) 440px;
}

.landing-marketing {
  background: var(--cw-ink);
  color: #fff;
  display: flex;
  align-items: center;
  padding: 3rem 3rem;
}

.landing-marketing-inner {
  max-width: 34rem;
  margin: 0 auto;
}

.landing-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: var(--cw-lime);
  color: var(--cw-ink);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  padding: 0.3rem 0.75rem 0.3rem 0.5rem;
  border-radius: 100px;
  text-decoration: none;
  margin-bottom: 1.75rem;
}
.landing-eyebrow:hover {
  color: var(--cw-ink);
  text-decoration: none;
  background: var(--cw-lime-strong);
}
.landing-eyebrow-mark {
  display: block;
  border-radius: 3px;
}

.landing-headline {
  font-size: clamp(2rem, 1.35rem + 2.6vw, 3rem);
  font-weight: 900;
  line-height: 1.08;
  letter-spacing: -0.02em;
  margin-bottom: 1.25rem;
  /* The global `h1, h2, h3 { color: var(--text) }` rule (an explicit selector)
     otherwise beats the inherited white from .landing-marketing, which would
     render near-black-on-black in light mode. This pane is always dark. */
  color: #fff;
}

.landing-subhead {
  font-size: 1.0625rem;
  line-height: 1.6;
  color: rgba(255, 255, 255, .78);
  margin-bottom: 2.25rem;
  max-width: 42ch;
}

.landing-pipeline {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: 1rem;
  margin-bottom: 2rem;
  padding: 1.25rem 0;
  border-top: 1px solid rgba(255, 255, 255, .14);
  border-bottom: 1px solid rgba(255, 255, 255, .14);
  overflow-x: auto;
}

.pipeline-step {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  flex-shrink: 0;
}

.pipeline-step-label {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--cw-lime);
  letter-spacing: 0.04em;
}

.pipeline-step-title {
  font-size: 0.9375rem;
  font-weight: 700;
  color: #fff;
  white-space: nowrap;
}

.pipeline-connector {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  opacity: 0.9;
}

.landing-truthful {
  font-size: 0.9375rem;
  line-height: 1.6;
  color: rgba(255, 255, 255, .78);
  border-left: 3px solid var(--cw-lime);
  padding-left: 1rem;
}
.landing-truthful strong {
  color: #fff;
}

.landing-auth {
  background: var(--surface);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2.5rem 2rem;
}

.landing-auth .login-card {
  width: 100%;
  max-width: 360px;
}

@media (max-width: 960px) {
  .landing-page {
    grid-template-columns: 1fr;
  }
  .landing-marketing {
    padding: 3rem 1.5rem 2.5rem;
  }
  .landing-headline {
    font-size: clamp(1.75rem, 1.3rem + 3vw, 2.5rem);
  }
  .landing-pipeline {
    gap: 0.625rem;
  }
}

@media (max-width: 768px) {
  .landing-pipeline {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
    overflow-x: visible;
  }
  .pipeline-step-title {
    white-space: normal;
  }
  .pipeline-connector {
    margin: 0.25rem 0 0.25rem 0.5rem;
  }
  .pipeline-connector svg {
    transform: rotate(90deg);
  }
}

@media (max-width: 480px) {
  .landing-marketing,
  .landing-auth {
    padding-left: 1.25rem;
    padding-right: 1.25rem;
  }
}

/* ── OAuth ("Sign in with LinkedIn") ──────────────────────────────────────── */
.oauth-divider {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 1.25rem 0;
  color: var(--text-muted);
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.oauth-divider::before,
.oauth-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

.btn-linkedin {
  background: #0a66c2;
  color: #fff;
  border-color: #0a66c2;
}
.btn-linkedin:hover {
  background: #084e96;
  border-color: #084e96;
  color: #fff;
  text-decoration: none;
  box-shadow: 0 2px 8px rgba(10, 102, 194, 0.3);
}

.btn-linkedin-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.125rem;
  height: 1.125rem;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.18);
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 1;
}

.link {
  color: var(--accent);
  font-weight: 500;
  text-decoration: none;
}

.link:hover {
  text-decoration: underline;
}

.form-error {
  display: block;
  margin-top: 0.375rem;
  font-size: 0.8125rem;
  color: var(--error);
}

/* ── Footer ────────────────────────────────────────────────────────────── */
.footer {
  border-top: 1px solid var(--border);
  background: var(--surface);
  padding: 1rem;
  margin-top: auto;
}

.footer-inner {
  max-width: 1100px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

.footer-group {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.footer-brand-link {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  color: var(--text-muted);
  font-weight: 500;
}
.footer-brand-link:hover {
  color: var(--accent);
}
.footer-brand-mark {
  width: 14px;
  height: 14px;
  border-radius: 3px;
  opacity: 0.9;
}

.footer-sep {
  opacity: 0.4;
}

/* ── Responsive adjustments ────────────────────────────────────────────── */
@media (max-width: 768px) {
  .card {
    padding: 1.25rem;
    border-radius: var(--radius-sm);
  }

  .nav-inner {
    padding: 0 0.75rem;
  }

  .nav-link {
    padding: 0.375rem 0.5rem;
  }

  .meta-list {
    grid-template-columns: 1fr;
    gap: 0.25rem;
  }

  .meta-list dt {
    margin-bottom: -0.2rem;
    font-size: 0.8125rem;
  }

  .status-header {
    flex-direction: column;
    align-items: flex-start;
  }

  .page-title {
    font-size: 1.375rem;
  }
}

@media (max-width: 480px) {
  .login-card {
    padding: 1.75rem 1.25rem;
  }

  /* Removed: this hid every nav link below 480px. :last-child here is the
     sign-out FORM, not a link, so :not(:last-child) matched all three — a phone
     user could not reach the dashboard, API keys or API access at all, only Sign
     out. The two-row nav further down gives them a row of their own instead. */
}

/* ============================================================
   Review screen — editable entry cards, repeatable rows,
   confidence chips, add/remove controls.
   ============================================================ */

/* ── Entries container ─────────────────────────────────────────────────── */
.entries-container {
  /* No visual styles — purely a mount point for JS-appended entries.
     Margin is handled by child .entry-row elements. */
}

/* ── Add-entry row (below each section's entries) ──────────────────────── */
.add-entry-row {
  margin-top: 0.25rem;
  padding-top: 0.75rem;
  border-top: 1px dashed var(--border);
}

.btn-add-entry {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--accent-light);
  gap: 0.3rem;
}
.btn-add-entry:hover {
  background: var(--accent);
  color: var(--accent-on);
  text-decoration: none;
}
.btn-add-entry:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ── Confidence chips ──────────────────────────────────────────────────── */
.conf-chip {
  display: inline-flex;
  align-items: center;
  padding: 0.1em 0.55em;
  border-radius: 100px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  white-space: nowrap;
  flex-shrink: 0;
}

.conf-chip-high {
  background: var(--success-bg);
  color: var(--success);
  border: 1px solid var(--success-border);
}

.conf-chip-medium {
  background: var(--warn-bg);
  color: var(--warn);
  border: 1px solid #fde68a;
}

.conf-chip-low {
  background: var(--error-bg);
  color: var(--error);
  border: 1px solid var(--error-border);
}

/* ── Repeatable lists (bullets, notes, skills within an entry) ─────────── */
.repeatable-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.repeatable-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.repeatable-row .form-input {
  flex: 1;
  min-width: 0;  /* allow flex shrink below content width */
}

/* ── Remove-row button (×) ─────────────────────────────────────────────── */
.btn-remove-row {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: var(--radius-xs);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
  padding: 0;
}
.btn-remove-row:hover {
  background: var(--error-bg);
  color: var(--error);
  border-color: var(--error-border);
}
.btn-remove-row:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ── Add-row button (inline, below a repeatable list) ──────────────────── */
.btn-add-row {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.25rem 0.625rem;
  border: 1px dashed var(--border);
  border-radius: var(--radius-xs);
  background: transparent;
  color: var(--accent);
  font-family: var(--font);
  font-size: 0.8125rem;
  font-weight: 500;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
  margin-top: 0.125rem;
}
.btn-add-row:hover {
  background: var(--accent-light);
  border-color: var(--accent);
  text-decoration: none;
}
.btn-add-row:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ── Language — mother-tongue checkbox group ────────────────────────────── */
.lang-mt-group {
  display: flex;
  flex-direction: column;
  justify-content: center;
  margin-bottom: 0;  /* override default .form-group margin when in a grid row */
}

.lang-mt-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  user-select: none;
  color: var(--text);
}

.lang-mt-checkbox {
  width: 1rem;
  height: 1rem;
  accent-color: var(--accent);
  cursor: pointer;
  flex-shrink: 0;
}

/* CEFR row uses a 3-col grid; collapse to 1-col on narrow screens */
.lang-cefr-row {
  grid-template-columns: 1fr 1fr 1fr;
}
@media (max-width: 640px) {
  .lang-cefr-row {
    grid-template-columns: 1fr;
  }
}

/* ── Responsive: single-column entry fields on small screens ───────────── */
@media (max-width: 600px) {
  .entry-fields .form-row {
    grid-template-columns: 1fr;
  }
}


/* ══ New conversion ════════════════════════════════════════════════════════
   Two ways in — a file or a LinkedIn URL — and nothing else on screen competing
   with that choice. Replaces a <select> of four modes (two of which were the same
   path, one of which asked the user to write JSON by hand).

   Motion here only ever answers something the person did: the pill slides when
   they switch source, the drop zone confirms when they choose a file, the button
   reports when it is working. Nothing animates on page load.
   ═══════════════════════════════════════════════════════════════════════════ */

.upload-hero { margin-bottom: 1.25rem; }
.upload-hero-sub {
  margin: .35rem 0 0;
  max-width: 56ch;
  color: var(--text-secondary);
  font-size: .95rem;
  line-height: 1.45;
}

/* ── Source picker ─────────────────────────────────────────────────────── */
.source-picker {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .75rem;
  padding: .35rem;
  margin-bottom: 1.5rem;
  background: var(--accent-light);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}

/* The moving part. Width is one grid column — the track minus its padding and the
   gap, halved — so the pill tracks the columns instead of guessing at 50%. */
.source-picker::before {
  content: "";
  position: absolute;
  top: .35rem;
  bottom: .35rem;
  left: .35rem;
  width: calc((100% - 1.45rem) / 2);
  background: var(--surface);
  border: 1px solid var(--accent);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  transition: transform 280ms cubic-bezier(.2, .9, .35, 1);
  pointer-events: none;
}
.source-picker[data-active="linkedin"]::before {
  transform: translateX(calc(100% + .75rem));
}

.source-tab {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: .85rem;
  padding: .85rem 1rem;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font: inherit;
  color: var(--text);
  text-align: left;
  cursor: pointer;
}
.source-tab:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--accent-ring);
}
.source-tab-glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  background: var(--surface);
  color: var(--text-secondary);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  transition: background 200ms ease, color 200ms ease, border-color 200ms ease;
}
/* --accent-on, not a literal colour: --accent flips to lime in dark mode, where a
   lime glyph on an --accent fill would be lime on lime. */
.source-tab-active .source-tab-glyph {
  background: var(--accent);
  color: var(--accent-on);
  border-color: var(--accent);
}
.source-tab:hover:not(.source-tab-active) .source-tab-glyph { border-color: var(--border-strong); }
.source-tab-label { display: flex; flex-direction: column; gap: .15rem; line-height: 1.25; }
.source-tab-title { font-weight: 700; font-size: .9375rem; }
.source-tab-hint { color: var(--text-muted); font-size: .78rem; }
.source-tab-active .source-tab-hint { color: var(--text-secondary); }

@media (max-width: 560px) {
  .source-picker { grid-template-columns: 1fr; }
  /* Stacked, the pill has nowhere to slide, so the tab paints its own state. */
  .source-picker::before { display: none; }
  .source-tab-active { background: var(--surface); border-color: var(--accent); }
}

/* ── Panels ────────────────────────────────────────────────────────────── */
.source-panel {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 200ms ease, transform 200ms ease;
}
.source-panel-active { opacity: 1; transform: translateY(0); }

/* ── Drop zone ─────────────────────────────────────────────────────────── */
/* Wraps the native input rather than replacing it: the input keeps its own
   keyboard behaviour and the <label for> makes the whole area a real target. */
.drop-zone {
  position: relative;
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1.1rem 1.25rem;
  background: var(--bg);
  border: 1.5px dashed var(--border-strong);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background 180ms ease, border-color 180ms ease;
}
.drop-zone:hover { border-color: var(--accent); background: var(--surface-hover); }
.drop-zone:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}
.drop-zone-hover {
  border-color: var(--accent);
  background: var(--accent-light);
}
.drop-zone-filled {
  border-style: solid;
  border-color: var(--accent);
  background: var(--surface);
}
.drop-zone-glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  color: var(--text-secondary);
  background: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  transition: color 180ms ease, background 180ms ease, border-color 180ms ease;
}
.drop-zone-filled .drop-zone-glyph {
  background: var(--accent);
  color: var(--accent-on);
  border-color: var(--accent);
  /* One short confirmation that the file landed — the only celebratory motion
     on the page, and it fires on the user's own action. */
  animation: drop-confirm 320ms cubic-bezier(.2, .9, .35, 1);
}
@keyframes drop-confirm {
  0%   { transform: scale(.82); }
  60%  { transform: scale(1.06); }
  100% { transform: scale(1); }
}
.drop-zone-slim { padding: .8rem 1rem; }
.drop-zone-slim .drop-zone-glyph { width: 36px; height: 36px; }
.drop-zone-body { display: flex; flex-direction: column; gap: .2rem; min-width: 0; }
.drop-zone-title { font-weight: 600; font-size: .9375rem; }
.drop-zone-or { color: var(--text-muted); font-weight: 400; }
.drop-zone-cta { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.drop-zone-hint {
  font-size: .8rem;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.drop-zone-filled .drop-zone-hint { color: var(--text); font-weight: 600; }
/* Visually hidden, still focusable and still the thing the label points at. */
.drop-zone-input {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  /* clip is deprecated but still the widest-support half of this pair; clip-path is
     what modern engines honour. Both, because a file input that escapes its clip
     renders the UA's own "No file chosen" next to ours. */
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ── LinkedIn panel ────────────────────────────────────────────────────── */
.linkedin-panel-intro {
  display: flex;
  gap: .75rem;
  padding: .8rem 1rem;
  margin-bottom: 1.25rem;
  background: var(--accent-light);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}
.linkedin-panel-title { margin: 0; font-weight: 600; font-size: .9rem; }
.linkedin-panel-sub { margin: .25rem 0 0; font-size: .82rem; color: var(--text-secondary); }
.form-input-lg { font-size: 1rem; padding: .7rem .85rem; }

.identity-nudge {
  display: flex;
  align-items: center;
  gap: .6rem;
  flex-wrap: wrap;
  margin-bottom: 1.25rem;
}

/* ── Output settings ───────────────────────────────────────────────────── */
/* Below a rule, because these are settings for the run rather than the choice
   the screen is actually asking the user to make. */
.output-strip {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  align-items: end;
  padding-top: 1.25rem;
  margin-top: .25rem;
  border-top: 1px solid var(--border-subtle);
}
@media (max-width: 560px) { .output-strip { grid-template-columns: 1fr; } }
/* The template list has exactly one entry. A <select> that cannot select
   anything is a decision the user does not have; this states the value instead. */
.output-static {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .55rem .75rem;
  background: var(--surface-hover);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  font-size: .875rem;
  color: var(--text-secondary);
}

/* ── Submit ────────────────────────────────────────────────────────────── */
.upload-actions { margin-top: 1.5rem; display: flex; align-items: center; gap: .75rem; }
.btn-submit-spinner {
  display: none;
  width: 14px; height: 14px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: submit-spin 620ms linear infinite;
}
/* A multipart upload can take seconds. Without this the page looks frozen and
   people click again, which is how you get duplicate jobs. */
.btn.is-busy { pointer-events: none; opacity: .82; }
.btn.is-busy .btn-submit-spinner { display: inline-block; }
.btn.is-busy .btn-submit-glyph { display: none; }
@keyframes submit-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .source-picker::before,
  .source-panel,
  .drop-zone,
  .drop-zone-glyph,
  .source-tab-glyph { transition: none; }
  .drop-zone-filled .drop-zone-glyph { animation: none; }
  .btn-submit-spinner { animation-duration: 2s; }
}


/* ══ Mobile ════════════════════════════════════════════════════════════════
   Audited against the real components rather than added speculatively. Note
   there is deliberately NO `overflow-x: hidden` safety net on html/body: it
   would mask real overflow instead of fixing it, and an overflow value other
   than `visible` on an ancestor silently disables `position: sticky` — which
   the nav, the review rail and the review action bar all rely on.
   ═══════════════════════════════════════════════════════════════════════════ */

/* iOS Safari zooms the whole page when a focused input's font-size is under
   16px, so tapping any field re-scaled the layout and the user had to pinch
   back out. Every control that can take focus goes to 16px on small screens;
   the desktop 15px is left alone. */
@media (max-width: 768px) {
  .form-input,
  .form-select,
  .form-textarea,
  .form-input-lg { font-size: 16px; }
}

/* The nav carried a brand lockup, up to three links, the signed-in email and a
   Sign out button in one fixed 56px row with no wrap. Below roughly 720px that
   cannot fit, and the overflow scrolled the entire page sideways. Brand on one
   row, actions on the next — everything stays visible and nothing is hidden
   behind a menu the user has to discover. */
@media (max-width: 720px) {
  .nav-inner {
    height: auto;
    min-height: 56px;
    flex-wrap: wrap;
    row-gap: .5rem;
    padding: .5rem .75rem;
  }
  .nav-links {
    width: 100%;
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: .25rem;
  }
  /* Pushed to the far end of its own row, so the destructive action is never
     adjacent to a navigation link the thumb was aiming for. */
  .nav-logout-form { margin-left: auto; }
}

@media (max-width: 480px) {
  .main { padding: 1.25rem .75rem 3rem; }
  .card { padding: 1rem; }
  .drop-zone { padding: .9rem 1rem; gap: .75rem; }
  .upload-actions { flex-wrap: wrap; }
  .upload-actions .btn { flex: 1 1 auto; justify-content: center; }
  .nav-brand-product { font-size: .8125rem; }
  .page-title { font-size: 1.25rem; }
}

/* Touch targets.
   Both conditions, deliberately. `pointer: coarse` is the meaningful test — a
   large tablet needs big targets and a small desktop window does not — but it is
   unverifiable in a headless render, and a phone in landscape is past most width
   breakpoints while still being a thumb. Either one qualifies. */
/* The landscape clause matters: a phone held sideways is ~844px WIDE, past the 720px
   fallback, while still being a thumb. Measured 23 targets under 40px there before it
   was added. */
@media (pointer: coarse), (max-width: 720px), (orientation: landscape) and (max-height: 500px) {
  .btn,
  .nav-link,
  .btn-add-row,
  .btn-add-entry,
  .btn-remove-row,
  .reject-btn,
  /* Measured at 16-22px before this: the row action in the jobs table, the
     breadcrumb hops, and the "Create one" link that is the only route to
     registration. All primary ways through the app, all too small to hit. */
  .link-action,
  .breadcrumb-link,
  .login-footer-link a,
  /* The logo is the "back to the dashboard" affordance on every page; at 28px it
     was the shortest tap target in the nav. */
  .nav-brand,
  .login-footer-link a {
    min-height: 40px;
    /* min-height does nothing on an inline box, and these are a mix of <a> and
       <button> whose display differs, so it is stated rather than assumed. */
    display: inline-flex;
    align-items: center;
  }
  .nav-link,
  .link-action,
  .btn-remove-row { justify-content: center; }
  .btn-remove-row { min-width: 40px; }
  /* Breadcrumb hops sit in a wrapping row; without this the taller links stack
     into a visibly loose ladder. */
  .breadcrumb { gap: .25rem .375rem; }
  /* Source tabs and drop zones are already well over 40px tall. */
}


/* ══ Orientation and short viewports ═══════════════════════════════════════
   Landscape on a phone is not "a small desktop". It is ~360-430px TALL, which
   is the dimension nothing else here budgets for, and on a notched device the
   camera housing eats one of the long edges.
   ═══════════════════════════════════════════════════════════════════════════ */

/* The home indicator overlaps the bottom of the screen, and the review action bar is
   pinned there. Portrait matters here too, so this one is not orientation-scoped. */
.review-actions {
  padding-bottom: max(.875rem, env(safe-area-inset-bottom));
}

/* The notch sits on a LONG edge, so in LANDSCAPE it eats the left or right of the
   content — invisible in portrait and in every desktop test. Scoped to landscape on
   purpose: the insets are 0 in portrait, so an unscoped max(1rem, …) would silently
   override the tighter padding the narrow-portrait rules set. Paired with
   viewport-fit=cover on the viewport meta, which alone would push content UNDER the
   notch; these insets are what pull it back out. */
@media (orientation: landscape) {
  .nav-inner,
  .main {
    padding-left: max(1rem, env(safe-area-inset-left));
    padding-right: max(1rem, env(safe-area-inset-right));
  }
}

@media (orientation: landscape) and (max-height: 500px) {
  /* The two-row nav is keyed off WIDTH (<=720px), which a 667px-wide landscape phone
     also matches — so it was spending ~100px of a 375px-tall viewport on navigation.
     There is plenty of width here; go back to one row and reclaim the height. */
  .nav-inner {
    height: auto;
    min-height: 44px;
    flex-wrap: nowrap;
    row-gap: 0;
  }
  .nav-links { width: auto; flex-wrap: nowrap; }
  .nav-logout-form { margin-left: .25rem; }
  /* The product name is the first thing that can go when width is the price of height. */
  .nav-brand-product { display: none; }

  /* Reclaim vertical space everywhere it is merely decorative. */
  .main { padding-top: 1rem; padding-bottom: 2rem; }
  .card { padding: 1rem; margin-bottom: 1rem; }
  .review-section { padding: 1rem; }
  .page-header { margin-bottom: 1rem; }
  .upload-hero { margin-bottom: .75rem; }
  .source-picker { margin-bottom: 1rem; }
  .drop-zone { padding: .75rem 1rem; }

  /* Sticky bars are worth their height in portrait. Two of them, in a 375px-tall
     viewport, are most of the screen — so the review action bar stops being sticky
     and simply sits at the end of the form. */
  .review-actions { position: static; }

  /* Touch targets stay at 40px: this is still a thumb. Nothing above shrinks them. */
}

/* A phone held in landscape with the keyboard open can be under 380px tall. */
@media (orientation: landscape) and (max-height: 380px) {
  .nav { position: static; }   /* give the whole viewport back to the content */
  .upload-hero-sub { display: none; }
}
