/* ENTRYPOINT — components: thesis, portfolio, form, buttons, toast */
/* ── THESIS ────────────────────────────────────────────── */
.thesis { padding: 80px 48px; border-bottom: 1px solid var(--t-border); }
.thesis-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0; border: 1px solid var(--t-border); }
.thesis-item {
  padding: 36px 32px;
  border-right: 1px solid var(--t-border);
  border-bottom: 1px solid var(--t-border);
  transition: background 0.15s;
}
.thesis-item:nth-child(2n) { border-right: none; }
.thesis-item:nth-child(n+3) { border-bottom: none; }
.thesis-item:hover { background: var(--t-bg-2); }
/* The snippets are decoration, but they are code, and an editor's colours are
   what make them read as code instead of as grey noise. The base colour is the
   plain one — parameter names, punctuation, the `self` — and the four spans
   below carry the rest; the values live in tokens.css. */
.thesis-code {
  font-family: 'SF Mono', 'Menlo', 'Monaco', monospace;
  font-size: 11px;
  line-height: 1.6;
  color: var(--t-fg-2);
  background: var(--t-bg-2);
  border-left: 2px solid var(--t-border-2);
  padding: 8px 10px;
  margin-bottom: 16px;
  overflow-wrap: anywhere;
}
.code-kw  { color: var(--t-code-kw); }
.code-fn  { color: var(--t-code-fn); }
.code-lit { color: var(--t-code-lit); }
.code-str { color: var(--t-code-str); }
.thesis-index {
  font-family: var(--font-display);
  font-size: 10px;
  letter-spacing: 0.12em;
  color: var(--t-fg-3);
  margin-bottom: 20px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.thesis-index::before { content: ''; width: 16px; height: 1px; background: var(--t-fg-3); }
.thesis-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 18px;
  color: var(--t-fg);
  margin-bottom: 12px;
  letter-spacing: -0.02em;
  line-height: 1.15;
}
.thesis-body { font-size: 13px; color: var(--t-fg-2); line-height: 1.65; }
.thesis-body + .thesis-body { margin-top: 12px; }

/* ── PORTFOLIO ─────────────────────────────────────────── */
.portfolio { padding: 80px 48px; border-bottom: 1px solid var(--t-border); }
/* Every cell draws its own 1px line as a shadow into the 1px gap, and the frame
   is the grid's border; the edge cells' shadows land on that border. No rule
   here knows which card sits where, so the count can change freely — the old
   per-position borders (nth-child(3n), n+4…) were right for one count only.
   A shadow, not a border: a border would double where two cells meet. */
.portfolio-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  border: 1px solid var(--t-border);
}
.portfolio-card {
  padding: 28px 24px;
  box-shadow: 0 0 0 1px var(--t-border);
  cursor: pointer;
  transition: background 0.15s;
  position: relative;
}
.portfolio-card:hover { background: var(--t-bg-2); }

/* The terminal after the cards. It closes the last row: as the grid's last
   child its position says how many cells are left — 3n+1 starts a fresh row
   (the cards filled theirs, so it is not needed), 3n+2 has two cells to its
   right edge, 3n has one. responsive.css redoes the count for two columns and
   drops it at one, where no row has a gap. The cell itself is the desktop:
   the hatch the grid used as filler before the terminal took the slot. The
   window sits on it, filling it, until red or yellow docks it (.is-docked,
   set by js/port-term.js) into an icon in the bottom-right corner.
   Its height comes from the cards it shares the row with: everything inside
   is absolute, so the text can never make the row taller. */
.port-next {
  /* Where the icon sits, from the bottom-right corner. The window shrinks
     toward the centre of the icon's artwork, so its transform-origin is
     derived from the same numbers: the art is 64px, centred in an 80px-wide
     button, above a 6px gap, a 16px label and 6px of padding. */
  --dock-x: 20px;
  --dock-y: 16px;
  position: relative;
  min-width: 0;
  min-height: 240px;
  overflow: hidden;
  background:
    repeating-linear-gradient(-45deg, transparent 0 9px, var(--t-border) 9px 10px),
    var(--t-bg);
  box-shadow: 0 0 0 1px var(--t-border);
}
.port-next:nth-child(3n+1) { display: none; }
.port-next:nth-child(3n+2) { grid-column: span 2; }
.port-next-window {
  position: absolute; inset: 0;
  display: flex;
  flex-direction: column;
  background: var(--term-bg);
  transform-origin: calc(100% - var(--dock-x) - 40px) calc(100% - var(--dock-y) - 60px);
  transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.3s, visibility 0s;
}
/* Macs draw these at 12px with 8px between them, as in the entry CLI; the
   hero's 11px/6px is a picture, these are buttons. The target grows in
   responsive.css, under ALVOS E PONTEIRO. */
.port-next .hero-macterm-lights { gap: 8px; }
.port-next .hero-macterm-light { width: 12px; height: 12px; }

/* Docked. Each control turns visible exactly when it starts to show — the
   window at once when undocking, the icon only when its fade begins — so
   nothing invisible can take a click; port-term.js moves focus to the icon at
   that same moment (transitionstart). The outgoing control keeps its
   visibility until its own animation ends. visibility is only ever set to
   hidden or inherit here, never to visible: under the entry overlay every
   section must stay hidden (terminal.css), and visible would punch through.
   With reduced motion, responsive.css zeroes these delays too, so docking is
   a cut. */
.port-next.is-docked .port-next-window {
  transform: scale(0.06);
  opacity: 0;
  visibility: hidden;
  transition: transform 0.45s cubic-bezier(0.6, 0, 0.8, 0.4), opacity 0.3s 0.15s, visibility 0s 0.45s;
}
.port-next-icon {
  position: absolute; right: var(--dock-x); bottom: var(--dock-y);
  width: 80px;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 6px 0;
  border-radius: var(--radius-sm);
  transform: scale(0.6);
  opacity: 0;
  visibility: hidden;
  transition: transform 0.2s, opacity 0.2s, visibility 0s 0.2s;
}
.port-next.is-docked .port-next-icon {
  transform: none;
  opacity: 1;
  visibility: inherit;
  transition: transform 0.35s 0.35s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.2s 0.35s, visibility 0s 0.35s;
}
/* After macOS's Terminal.app: a dark squircle with a glassy rim, a white >
   and a grey _ set beside it. */
.port-next-icon-art {
  position: relative;
  width: 64px; height: 64px;
  border-radius: 15px;
  background: linear-gradient(to bottom, var(--t-border-2), var(--t-bg-2));
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,0.2),
    inset 0 1px 0 rgba(255,255,255,0.28),
    0 8px 18px rgba(0,0,0,0.55);
  font-family: 'SF Mono', 'Menlo', monospace;
  line-height: 1;
  transition: transform 0.15s;
}
.port-next-icon:hover .port-next-icon-art { transform: translateY(-2px); }
.port-next-icon-gt {
  position: absolute; left: 11px; top: 9px;
  font-size: 24px; font-weight: 700;
  color: var(--term-fg-bright);
}
.port-next-icon-us {
  position: absolute; left: 28px; top: 10px;
  font-size: 20px;
  color: var(--term-dim);
}
.port-next-icon-label {
  font-family: -apple-system, 'SF Pro', sans-serif;
  font-size: 13px; font-weight: 600; line-height: 16px;
  color: var(--t-fg);
  text-shadow: 0 1px 2px rgba(0,0,0,0.6);
}

.port-next-body {
  flex: 1;
  padding: 16px 20px;
  font-family: 'SF Mono', 'Menlo', monospace;
  font-size: 12px; line-height: 1.6;
  color: var(--term-fg);
}
/* pre per line, not on the body: on the body, the indentation between the
   line <div>s would render as blank lines. */
.port-next-body > div { white-space: pre; min-height: 1.6em; }
.port-next-dim { color: var(--term-dim); }
.port-next-bar { color: var(--accent); }

/* The resting frame of every animation below is the one shown with
   prefers-reduced-motion — the global rule in responsive.css cuts each
   animation to one 0.01ms pass, which lands back on these base values:
   first spinner frame, bar a little over half full. */
.port-next-spin::before {
  content: '⠋';
  display: inline-block; width: 1ch;
  animation: port-next-spin 0.8s steps(1) infinite;
}
@keyframes port-next-spin {
  0%  { content: '⠋'; } 10% { content: '⠙'; } 20% { content: '⠹'; }
  30% { content: '⠸'; } 40% { content: '⠼'; } 50% { content: '⠴'; }
  60% { content: '⠦'; } 70% { content: '⠧'; } 80% { content: '⠇'; }
  90% { content: '⠏'; }
}
/* The bar is twenty cells of track with twenty full blocks over it, clipped
   by width — steps(20) so it fills a whole block at a time, as a terminal
   would. Fills in 4s, holds full for 1s, starts again. */
.port-next-track {
  position: relative;
  display: inline-block;
  vertical-align: top;
  width: 20ch;
}
.port-next-track::before { content: '░░░░░░░░░░░░░░░░░░░░'; }
.port-next-track::after {
  content: '████████████████████';
  position: absolute; top: 0; left: 0;
  width: 11ch;
  overflow: hidden;
  animation: port-next-fill 5s infinite;
}
@keyframes port-next-fill {
  0%   { width: 0;    animation-timing-function: steps(20, end); }
  80%  { width: 20ch; }
  100% { width: 20ch; }
}
/* Nobody watches a docked window load, nor one behind the entry overlay —
   which is where every visit starts. Both animations step `content` and
   `width`, so each frame is style and layout work: they run only while the
   window can be seen. (The overlay minimized to its corner uncovers the site,
   so that state counts as seen.) */
.port-next.is-docked .port-next-spin::before,
.port-next.is-docked .port-next-track::after,
.cli-open:not(:has(#screen-cli.is-min)) .port-next-spin::before,
.cli-open:not(:has(#screen-cli.is-min)) .port-next-track::after { animation-play-state: paused; }

/* Logo slot. No box: the logo lines up left with the tag, name and
   description. */
.port-logo-slot {
  width: 100%;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  margin-bottom: 16px;
}
/* White silhouette, the same for every brand. Two reasons: the marks arrive in
   different colours and AbacatePay's dark green vanished on black; and a wall of
   five palettes would fight the house rule of a single accent.
   brightness(0) flattens everything to black while preserving alpha; invert(1)
   returns it white — which is why it works for light and dark logos alike. */
.port-logo-img {
  max-height: 28px;
  max-width: 80%;
  object-fit: contain;
  /* contain centres the drawing inside the 120px box, which left each logo with a
     different left inset depending on its aspect ratio. */
  object-position: left center;
  filter: brightness(0) invert(1);
  opacity: 0.85;
}
.portfolio-card:hover .port-logo-img { opacity: 1; }

.port-tag {
  display: inline-flex; align-items: center;
  padding: 2px 7px;
  background: transparent;
  border: 1px solid var(--t-border-2);
  border-radius: var(--radius-md);
  font-family: var(--font-display);
  font-size: 9px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--t-fg-3);
  margin-bottom: 10px;
}
.port-name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 18px;
  letter-spacing: -0.02em;
  color: var(--t-fg);
  margin-bottom: 8px;
}
.port-desc { font-size: 12px; color: var(--t-fg-2); line-height: 1.55; }
.port-arrow {
  position: absolute; bottom: 20px; right: 20px;
  font-family: var(--font-display);
  font-size: 14px; color: var(--t-fg-3);
  transition: color 0.15s, transform 0.15s;
}
.portfolio-card:hover .port-arrow { color: var(--t-fg); transform: translateX(3px); }

/* ── APPLY ─────────────────────────────────────────────── */
.apply-section {
  padding: 80px 48px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  border-bottom: 1px solid var(--t-border);
}
.apply-left { padding-right: 64px; border-right: 1px solid var(--t-border); }
.apply-right { padding-left: 64px; }
.apply-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 44px;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--t-fg);
  margin-bottom: 20px;
  /* The headline on the home used to fit one line; the longer question that
     replaced it wraps, and left to itself it dropped a single word onto the
     second line. `balance` splits the lines evenly instead. It only acts on
     short blocks (browsers cap it at a few lines), which is exactly what both
     users of this class are — here and the <h1> of /apply. */
  text-wrap: balance;
}
.apply-body {
  font-size: 15px;
  color: var(--t-fg-2);
  line-height: 1.65;
  margin-bottom: 40px;
}
.apply-step { display: flex; align-items: flex-start; gap: 14px; margin-bottom: 20px; }
.apply-step-num {
  font-family: var(--font-display);
  font-size: 10px; font-weight: 400;
  letter-spacing: 0.1em;
  color: var(--t-fg-3);
  border: 1px solid var(--t-border-2);
  width: 24px; height: 24px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.apply-step-title { font-size: 13px; font-weight: 600; color: var(--t-fg); margin-bottom: 2px; }
.apply-step-sub { font-size: 12px; color: var(--t-fg-3); }

.form-field { margin-bottom: 14px; }
.form-label {
  font-family: var(--font-display);
  font-size: 10px;
  font-weight: 400;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--t-fg-2);
  display: block;
  margin-bottom: 5px;
}
/* O "(optional)" do label: menor e apagado, para o obrigatório continuar
   sendo o caso normal aos olhos de quem lê. */
.form-optional { font-weight: 400; color: var(--t-fg-2); }
.form-input {
  width: 100%;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--t-fg);
  background: var(--t-bg-2);
  border: 1px solid var(--t-border-2);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  transition: border-color 0.15s;
  /* no outline:none — the focus ring comes from :focus-visible in base.css */
}
.form-input::placeholder { color: var(--t-fg-3); }
.form-input:focus { border-color: var(--t-fg); }

/* ── BUTTONS ───────────────────────────────────────────── */
.btn-primary {
  display: inline-flex; align-items: center;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: var(--t-fg);
  color: var(--t-bg);
  border: none;
  padding: 11px 22px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: opacity 0.15s;
}
.btn-primary:hover { opacity: 0.75; }
.btn-ghost {
  display: inline-flex; align-items: center;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: transparent;
  color: var(--t-fg-2);
  border: 1px solid var(--t-border-2);
  padding: 10px 22px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.btn-ghost:hover { border-color: var(--t-fg); color: var(--t-fg); }

/* Square icon-only button. */
.btn-icon {
  width: 32px; height: 32px;
  border: 1px solid var(--t-border-2);
  background: transparent;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--t-fg-2);
  font-size: 13px;
  transition: background 0.15s, color 0.15s;
}
/* Terminal button: wider than the 32px squares, labelled ▸_. It must come AFTER
   .btn-icon — same specificity, so the one below wins the width. */
.nav-terminal {
  width: auto;
  padding: 0 10px;
  gap: 4px;
  font-family: var(--font-display);
  font-size: 11px;
}
.btn-icon:hover { background: var(--t-border); color: var(--t-fg); }

/* ── TOAST ─────────────────────────────────────────────── */
#toast {
  position: fixed; bottom: 28px; right: 28px; z-index: 999;
  background: var(--t-fg);
  color: var(--t-bg);
  padding: 14px 20px;
  border-radius: var(--radius-sm);
  font-family: var(--font-display);
  font-size: 11px;
  letter-spacing: 0.08em;
  transform: translateY(60px); opacity: 0;
  transition: all 0.3s cubic-bezier(0.16,1,0.3,1);
  pointer-events: none;
}

/* ── AMBER ACCENT ──────────────────────────────────────── */
/* Overrides folded into the base rules. They come after those rules in the
   cascade, so they need no !important. */
.hero-title { font-size: 96px; letter-spacing: -0.055em; line-height: 0.92; }
.section-label { color: var(--accent); }
.thesis-index, .apply-step-num {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--accent-soft);
}
.port-tag { background: var(--accent); color: var(--accent-ink); font-weight: 600; }
.btn-primary { background: var(--accent); color: var(--accent-ink); }
.btn-primary:hover { opacity: 1; transform: translateY(-1px); }

/* ── FORM STATES ───────────────────────────────────────── */
.form-error {
  font-family: var(--font-display);
  font-size: 10px;
  letter-spacing: 0.06em;
  color: var(--t-error);
  margin-top: 6px;
}
.form-input[aria-invalid="true"] { border-color: var(--t-error); }

.form-submit { width: 100%; justify-content: center; padding: 13px; }

/* Honeypot. display:none, e não uma classe de "visually hidden": aqui esconder
   de todo mundo é o objetivo, leitor de tela incluído. De quebra, é o que o tira
   da conta de focáveis da suíte, que filtra por offsetParent !== null. */
.form-hp { display: none; }

.form-submit:disabled { opacity: 0.5; cursor: progress; }

.form-status {
  font-family: var(--font-display);
  font-size: 11px;
  letter-spacing: 0.06em;
  margin-top: 14px;
  text-align: center;
}
.form-status.is-ok      { color: var(--t-success); }
.form-status.is-error   { color: var(--t-error); }
.form-status.is-pending { color: var(--t-fg-2); }

/* The textarea must not be draggable outside its column. */
textarea.form-input { resize: vertical; line-height: 1.5; }
/* The native arrow goes because it clashes with the rest — but dropping it and
   putting nothing back left a control that measured identical to a text input:
   same border, same fill, no affordance saying it opens a list. The chevron
   comes back drawn in the site's own ink, as an inline SVG in a data URI (no
   extra request, and no glyph standing in for an icon). The right padding makes
   room for it so a long stage name never runs under it. */
select.form-input {
  appearance: none;
  cursor: pointer;
  padding-right: 34px;
  background-image: var(--chevron-down);
  background-repeat: no-repeat;
  background-position: right 12px center;
}
/* The empty option is a prompt, not an answer. Rendered in --t-fg like a real
   value, "Select stage" read as a field already filled in — on a required
   field, which is the worst place for that. While it is the one selected the
   control wears the same grey as the placeholders beside it, and goes to full
   --t-fg the moment a real stage is picked.
   Keyed on the empty option rather than on :invalid so it keeps working if the
   field ever stops being required. (:has() is already load-bearing in
   terminal.css; same support floor.) */
select.form-input:has(option[value=""]:checked) { color: var(--t-fg-3); }
