/*
 * All layout/component styling for the site. Color values should come from
 * the --ctp-* custom properties defined in catppuccin.css, not hardcoded
 * hex — that's the one file to touch to re-theme the whole site.
 *
 * Two unrelated "pages" are styled here:
 *   - .tmux / .pane-* / .term-*  → the terminal homepage (layouts/index.html)
 *   - body.plain / .plain-page   → the plain fallback pages (layouts/_default/*)
 */

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--ctp-crust);
  color: var(--ctp-text);
  font-family: "Cascadia Code", "JetBrains Mono", "Fira Code", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 15px;
  line-height: 1.5;
}

a { color: var(--ctp-blue); }
a:hover { color: var(--ctp-sky); }

/* ---- tmux chrome ---- */

.tmux {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

/* Styled after the site owner's own real tmux config: catppuccin/tmux,
   flavor mocha, window-status-style "rounded", status bar at the bottom
   (this section renders after .tmux-panes in the markup, so it lands there
   with no extra CSS needed), status-left empty and everything on
   status-right as icon+text module pills. Colors below are the exact
   defaults that config resolves to (@catppuccin_window_number_color etc.)
   — see git history / ROADMAP.md if this ever needs re-deriving from the
   plugin source. */
.tmux-status {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  background: var(--ctp-mantle);
  color: var(--ctp-subtext1);
  padding: 0.3rem 0.75rem;
  font-size: 0.85rem;
  border-top: 1px solid var(--ctp-surface0);
  flex: 0 0 auto;
}

/* one pane is ever visible at a time (switched via .tmux-window buttons),
   so unlike a side-by-side layout this doesn't need its own gap/scroll
   handling beyond what .tmux-windows already has. */
.tmux-windows {
  display: flex;
  gap: 0.35rem;
  overflow-x: auto;
  /* lets this shrink and scroll independently on narrow viewports instead of
     squeezing the right-side modules off-screen or wrapping mid-button */
  min-width: 0;
}

/* Each window tab is a two-color pill: a number half and a name half,
   matching @catppuccin_window_status_style "rounded" exactly (real tmux
   draws this with reverse-video separator glyphs; a rounded container that
   clips two flush-abutting halves is the direct CSS equivalent — same
   result, no font/glyph dependency).
   border-radius: 999px, not a small px value — any radius at or above half
   the pill's own height gets clamped by CSS to exactly that, which is what
   actually produces true semicircular end-caps (a stadium/pill shape) on a
   wide rectangle. A modest radius like 4px only rounds the corners a
   little; confirmed against a real screenshot of the reference tmux bar
   that the ends read as full semicircles, not soft corners. */
.tmux-window {
  flex: 0 0 auto;
  display: inline-flex;
  /* reset button chrome — this is a UI toggle, not form input. `border:
     none`/`padding: 0` alone left `appearance: auto` in place, which kept
     the native OS button background (an off-white ~#efefef, not any
     color this page ever sets) rendering underneath the child spans —
     visible as a thin light outline right at the rounded edge, where the
     button's own square-ish native box didn't quite align pixel-for-pixel
     with its children's clipped pill shape. `appearance: none` +
     `background: none` remove that layer entirely, so there's nothing
     left to peek through regardless of any sub-pixel rounding. */
  appearance: none;
  background: none;
  font: inherit;
  border: none;
  padding: 0;
  cursor: pointer;
  border-radius: 999px;
  overflow: hidden;
  white-space: nowrap;
}

/* Buttons repurposed as UI toggles like this still need a visible focus
   indicator for keyboard users — just not the browser's default one,
   which (like the background above) doesn't respect the pill's rounded
   clip and would show as the same square-edged artifact. outline-offset
   keeps it outside the pill entirely, sidestepping that. */
.tmux-window:focus-visible {
  outline: 2px solid var(--ctp-lavender);
  outline-offset: 2px;
}

.tmux-window-number,
.tmux-window-label {
  padding: 0.05rem 0.5rem;
}

.tmux-window-number {
  color: var(--ctp-crust);
  background: var(--ctp-overlay2);
}

.tmux-window-label {
  color: var(--ctp-text);
  background: var(--ctp-surface0);
}

.tmux-window.active .tmux-window-number {
  background: var(--ctp-mauve);
}

.tmux-window.active .tmux-window-label {
  background: var(--ctp-surface1);
}

.tmux-spacer { flex: 1; }

/* status-right: the three icon+text modules (person/session/uptime), built
   by static/js/shell.js. Confirmed against a reference screenshot
   (pixel-sampled — tracing each edge's x-position across every y row in
   the icon's height, not eyeballed) that the real shape is:
     - ONE continuous surface0 background behind the whole group, with no
       gap or color break between modules — every module's text segment
       uses that same background, and the space between modules is just
       that background showing through, not a separator glyph.
     - EVERY icon (not only the first) has its own rounded LEFT edge that
       emerges from that shared background — real tmux prepends the same
       left-separator glyph before each module's icon, not just the
       first — but a FLAT (unrounded) right edge where it meets its own
       text, since there's no separator glyph between an icon and its
       text at all.
     - The group's right end (after the last module's text) is flat, not
       rounded — confirmed the same way; there's no closing cap.
   So each module owns its own asymmetric rounding (left corners only);
   the container itself is a plain rectangle providing the shared
   background, not a pill shape — the reverse of .tmux-window, where each
   window tab genuinely is its own separate, fully-rounded pill. */
.tmux-right-status {
  display: flex;
  flex: 0 0 auto;
  background: var(--ctp-surface0);
}

.tmux-module {
  display: inline-flex;
  white-space: nowrap;
}

.tmux-module-icon {
  display: flex;
  align-items: center;
  padding: 0.05rem 0.4rem;
  color: var(--ctp-crust);
  border-radius: 999px 0 0 999px; /* rounded left corners only — see comment above */
}

.tmux-module-icon svg {
  width: 0.9em;
  height: 0.9em;
}

.tmux-module-text {
  padding: 0.05rem 0.5rem;
  color: var(--ctp-text);
}

/* Below this width there isn't room for the window tabs *and* the
   right-status modules without one covering the other (reported on Android
   phones, e.g. a ~360-400px viewport) — window 0 (the live shell) has no
   button anyway once the bar is hidden, so it just stays the only pane;
   visitors reach the other sections via cd/ls/cat instead of tapping tabs.
   The uptime module is dropped too, keeping just user/host, since it's the
   one right-status module that grows over time and was the direct cause of
   window tabs getting progressively covered as a session stayed open. */
@media (max-width: 640px) {
  .tmux-windows,
  .tmux-module-uptime {
    display: none;
  }
}

.tmux-panes {
  display: flex;
  flex: 1 1 auto;
  min-height: 0;
}

.pane {
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* higher specificity than .pane-main's own `display: flex` below is required
   here — the `hidden` attribute's UA-stylesheet `display: none` is lowest
   priority in the cascade and would otherwise lose to it. */
.pane[hidden] {
  display: none;
}

.pane-main {
  flex: 1 1 auto;
  padding: 0.75rem 1rem;
  overflow-y: auto;
  cursor: text;
}

/* the pre-run transcript panes (windows 1-5) aren't click-to-type like the
   live shell (window 0) — cursor: text there would be a misleading affordance */
.pane-tab {
  cursor: auto;
}

.noscript-links {
  padding: 0.5rem 1rem;
  color: var(--ctp-subtext1);
  background: var(--ctp-mantle);
  margin: 0;
}

/* ---- terminal scrollback + input line ---- */

.term-scrollback .line {
  white-space: pre-wrap;
  word-break: break-word;
}

.term-scrollback pre.output,
.term-scrollback pre.error {
  margin: 0.15rem 0 0.6rem 0;
  white-space: pre-wrap;
  word-break: break-word;
  font-family: inherit;
}

.term-scrollback pre.error { color: var(--ctp-red); }

/* motd's ASCII-art banner is fixed-width — pre-wrap/break-word (right for
   prose output above) would wrap it mid-character on a narrow viewport and
   destroy its shape. Scroll it horizontally instead of reflowing it. */
.term-scrollback pre.ascii-art {
  white-space: pre;
  overflow-x: auto;
}

.echo-prompt { color: var(--ctp-green); }
.echo-prompt .prompt-path { color: var(--ctp-blue); }
.echo-cmd { color: var(--ctp-text); }

.term-inputline {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
}

/* margin instead of a gap on .term-inputline: a flex `gap` would also land
   between #typed and #cursor, leaving a visible sliver between the last
   typed character and the cursor — the cursor needs to sit flush against it. */
.prompt { color: var(--ctp-green); white-space: nowrap; margin-right: 0.4em; }
.prompt .prompt-path { color: var(--ctp-blue); }

.term-typed { color: var(--ctp-text); white-space: pre-wrap; word-break: break-word; }

.cursor {
  /* explicit box, not sized from its text content: a lone space character
     is trailing whitespace at the end of the flex line, and browsers
     collapse that to zero advance width — so the background never painted
     anything no matter what the animation/color said. */
  display: inline-block;
  width: 0.6em;
  /* align-self: stretch (not a fixed height) rather than trying to match the
     baseline: an empty inline-block's baseline is its own bottom margin
     edge, so with the container's `align-items: baseline` it would sit with
     its bottom pinned to the text baseline instead of the descent line,
     floating visibly above where real glyphs sit. Stretching to the full
     flex line box lines its top/bottom up with the text within ~1px. */
  align-self: stretch;
  background: var(--ctp-text);
  animation: blink 1s steps(1) infinite;
}

@keyframes blink {
  50% { opacity: 0; }
}

/* the real <input> shell.js listens on — invisible but focusable, never `display:none`
   (that would drop focus and break keyboard input; see shell.js's input-handling comment).
   1px, not 0: a zero-size element's bounding box is empty, which some automation/
   accessibility tooling treats as "not typeable" and refuses to dispatch keystrokes into,
   even once it's focused. 1x1 + opacity:0 stays invisible while keeping a real box. */
.hidden-input {
  /* top/left: 0, not left unset — with no positioned ancestor, an
     absolutely-positioned element with no top/left falls back to its
     static position, which for this element (last child of <body>, right
     after the full-viewport .tmux div) sits just past the bottom of the
     page. That alone made the whole document a few px taller than the
     viewport, which is a genuine `overflow-y` condition — a scrollbar can
     render for that even without anything ever scrolling to reveal it. */
  position: absolute;
  top: 0;
  left: 0;
  opacity: 0;
  height: 1px;
  width: 1px;
  pointer-events: none;
}

/* ---- plain fallback pages (/cv/, /certificates/, /projects/) ---- */

body.plain {
  background: var(--ctp-base);
}

.plain-page {
  max-width: 44rem;
  margin: 0 auto;
  padding: 2rem 1.25rem 4rem;
}

.plain-page .back-link {
  display: inline-block;
  margin-bottom: 1.5rem;
  color: var(--ctp-overlay1);
}

.plain-page h1 { color: var(--ctp-mauve); }
.plain-page h2 { color: var(--ctp-lavender); margin-top: 2rem; }
.plain-page h3 { color: var(--ctp-blue); margin-bottom: 0.25rem; }

.plain-page .meta { color: var(--ctp-overlay1); margin-top: 0; font-size: 0.9em; }

.plain-page ul.cards { list-style: none; padding: 0; }
.plain-page ul.cards li {
  border: 1px solid var(--ctp-surface0);
  border-radius: 6px;
  padding: 0.75rem 1rem;
  margin-bottom: 0.75rem;
}
