/* Retro effects shared by the homepage and /vibe. Colours and fonts come from each page's :root. */

/* Accent themes, chosen per visit by the inline script in each page's <head> (blue without JS).
   --pixel fills; --on-pixel is text on those fills; --pixel-text is accent text on --paper;
   --pixel-hi and --pixel-lo are the accent's bevel highlight and shadow in shaded pixel art. */
html[data-theme="blue"]   { --pixel: #1f3bd6; --on-pixel: var(--paper); --pixel-text: #1f3bd6; --pixel-hi: #6f86f0; --pixel-lo: #11247f; }
html[data-theme="green"]  { --pixel: #10633b; --on-pixel: var(--paper); --pixel-text: #10633b; --pixel-hi: #36a167; --pixel-lo: #073a22; }
html[data-theme="red"]    { --pixel: #c52e13; --on-pixel: var(--paper); --pixel-text: #c52e13; --pixel-hi: #ee7c63; --pixel-lo: #7a1a0a; }
html[data-theme="yellow"] { --pixel: #d7a13f; --on-pixel: var(--ink);   --pixel-text: #8a5d0a; --pixel-hi: #f3d791; --pixel-lo: #a4710e; }

/* ── Pixel cursor (fine pointers only; elements are added by JS) ── */
.pixel-cursor {
  position: fixed;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  pointer-events: none;
  z-index: 9999;
  opacity: 0;
  transition: opacity 0.25s ease;
}

.pixel-cursor svg {
  position: absolute;
  top: 0;
  left: 0;
  display: block;
}

.pixel-cursor .px-o { fill: var(--paper); }
.pixel-cursor .px-i { fill: var(--ink); }

/* Retro link hand and hourglass: paper body, ink outline, finger lines and sand */
.pixel-cursor .pixel-hand .px-o,
.pixel-cursor .pixel-hourglass .px-o { fill: var(--ink); }
.pixel-cursor .pixel-hand .px-i,
.pixel-cursor .pixel-hourglass .px-i { fill: var(--paper); }

/* Hourglass is centred on the pointer; its four sand frames each show for a quarter cycle */
.pixel-cursor .pixel-hourglass {
  position: absolute;
  left: -12px;
  top: -16px;
  display: none;
}

.pixel-cursor .pixel-hourglass svg { visibility: hidden; }

.pixel-cursor .pixel-hand {
  left: -12px; /* fingertip sits on the pointer */
  display: none;
}

/* DOS preview window over work rows (fine pointers only; element added by JS) */
.dos-window {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 9997;
  display: none;
  pointer-events: none;
  padding: 3px;
  background: var(--pixel);
  color: var(--on-pixel);
  box-shadow: 6px 6px 0 var(--ink); /* text-mode shadow, one cell down and right */
  font-family: 'Silkscreen', var(--mono);
  font-size: 8px;
  line-height: 1;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
}

.dos-window.is-open,
.dos-window.is-closing { display: block; }
.dos-window.is-open { animation: dos-open 120ms steps(1, end) both; }
.dos-window.is-closing { animation: dos-close 120ms steps(1, end) both; }

.dos-frame { border: 3px double var(--on-pixel); }

.dos-title {
  display: flex;
  gap: 6px;
  background: var(--paper);
  color: var(--pixel-text);
  padding: 3px 5px 2px;
}

.dos-body {
  display: grid;
  grid-template-columns: auto auto;
  justify-content: start;
  gap: 5px 8px;
  padding: 7px 8px 8px;
}

.dos-body span { min-height: 8px; }
.dos-body .dos-wide { grid-column: 1 / -1; }

.pixel-bit {
  position: fixed;
  top: 0;
  left: 0;
  width: 4px;
  height: 4px;
  background: var(--ink);
  pointer-events: none;
  z-index: 9998;
  scale: 0;
}

.pixel-bit.is-big { width: 8px; height: 8px; }
.pixel-bit.is-blue { background: var(--pixel); }
.pixel-bit.is-trail { scale: 1; animation: pixel-fade 700ms steps(1, end) forwards; }

html.has-cursor,
html.has-cursor * { cursor: none !important; }

html.has-cursor input,
html.has-cursor textarea { cursor: text !important; }

html.cursor-visible .pixel-cursor { opacity: 1; }
html.cursor-over-field .pixel-cursor { opacity: 0; }

html.cursor-link .pixel-arrow { display: none; }
html.cursor-link .pixel-hand {
  display: block;
  animation: pixel-bob 0.5s steps(1, end) infinite;
}

html.cursor-wait .pixel-arrow,
html.cursor-wait .pixel-hand { display: none; }
html.cursor-wait .pixel-hourglass { display: block; }
html.cursor-wait .pixel-hourglass svg { animation: pixel-sand 1s steps(1, end) infinite; }
html.cursor-wait .pixel-hourglass svg:nth-child(2) { animation-delay: -0.75s; }
html.cursor-wait .pixel-hourglass svg:nth-child(3) { animation-delay: -0.5s; }
html.cursor-wait .pixel-hourglass svg:nth-child(4) { animation-delay: -0.25s; }

@keyframes pixel-sand {
  0%        { visibility: visible; }
  25%, 100% { visibility: hidden; }
}

@keyframes pixel-bob {
  0%   { transform: translateY(0); }
  50%  { transform: translateY(-1px); }
  100% { transform: translateY(0); }
}

@keyframes dos-open {
  0%        { scale: 0; }
  33%       { scale: 0.5; }
  66%, 100% { scale: 1; }
}

@keyframes dos-close {
  0%        { scale: 1; }
  33%       { scale: 0.5; }
  66%, 100% { scale: 0; }
}

/* Size and fall share one transform so shrinking doesn't also shorten the drop */
@keyframes pixel-fade {
  0%   { transform: translateY(0) scale(1); }
  25%  { transform: translateY(calc(var(--fall) / 2)) scale(1); }
  50%  { transform: translateY(calc(var(--fall) / 2)) scale(0.5); }
  75%  { transform: translateY(var(--fall)) scale(0.5); }
  100% { transform: translateY(var(--fall)) scale(0); }
}

@media (prefers-reduced-motion: reduce) {
  html.cursor-link .pixel-hand,
  .dos-window.is-open,
  .dos-window.is-closing { animation: none; }
}

/* Dithered DOS layer drawn over the photo by JS; cleared cells let the real photo through */
.hero-dither {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  image-rendering: pixelated;
}

@media (max-width: 660px) {
  .hero-dither { border-radius: 50%; }
}

/* Blinking block cursor, shared by the clock, typed labels and terminal */
.block-cursor {
  display: inline-block;
  width: 0.6em;
  height: 1em;
  margin-left: 0.1em;
  vertical-align: -0.15em;
  background: currentColor;
  animation: block-blink 1s steps(1, end) infinite;
}

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

/* BUCK: a filled-in DOS form field, value on a dotted fill line that runs a little past the text */
.dos-field {
  color: var(--pixel-text);
  padding: 0 2ch 1px 0;
  border-bottom: 1px dotted var(--pixel-text);
}

/* The cursor takes no space, so showing it never nudges the line */
.dos-field-cursor { display: none; margin-right: -0.7em; }

@media (hover: hover) and (pointer: fine) {
  .dos-field:hover { color: var(--on-pixel); background: var(--pixel); }
  .dos-field:hover .dos-field-cursor { display: inline-block; }
}

/* Name glitch: a canvas laid over one letter of the hero heading (see retro.js) */
.glitch-host { position: relative; }

.glitch-letter {
  position: absolute;
  pointer-events: none;
}

/* ── Menu bar: a DOS program's top row (the footer's function keys are its bottom row) ── */
.menubar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 34px 0 6px;
  border-bottom: 1px solid var(--ink);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 400; /* the same cut as the footer's function keys, so the two bars match */
  line-height: 1;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  position: relative;
  z-index: 1; /* its tap areas reach below the rule, over content that animates in with a transform */
}

.menu {
  display: flex;
  list-style: none;
}

.menu-item {
  position: relative;
  display: block;
  padding: 3px 8px;
  color: var(--ink);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}

/* The first letter is marked like a DOS menu shortcut (visual only: no keys are bound) */
.menu-key { color: var(--pixel-text); }

/* Selected: a hard-cut --pixel block, the marked letter underlined */
.menu-item:hover,
.menu-item:focus-visible {
  color: var(--on-pixel);
  background: var(--pixel);
  outline: none;
}

.menu-item:hover .menu-key,
.menu-item:focus-visible .menu-key {
  color: var(--on-pixel);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.menu-item:focus { outline: none; }

.menubar .prompt-clock { color: var(--mid); }

/* Phones: tighter items so the bar stays one row at 360px; below that the clock shows just the time */
@media (max-width: 660px) {
  .menubar { gap: 6px; padding-top: 24px; letter-spacing: 0.04em; }
  .menu { gap: 6px; }
  .menu-item { padding: 3px 5px; }
}

@media (max-width: 359px) {
  .prompt-prefix { display: none; }
}

/* Touch: 44px tap areas that don't move the layout */
@media (hover: none) and (pointer: coarse) {
  .menu-item::after {
    content: '';
    position: absolute;
    inset: -14px -3px;
  }
  /* The bar sets line-height 1, so the clock reaches further up and down to make 44px, and only as far
     sideways as the gap, so it never takes taps meant for LinkedIn */
  .menubar .prompt-clock::after { inset: -17px -3px; }
  .menu-item:hover:not(:focus-visible) { color: var(--ink); background: none; }
  .menu-item:hover:not(:focus-visible) .menu-key { color: var(--pixel-text); text-decoration: none; }
}

/* Prompt clock at the right of the menu bar */
.prompt-clock { cursor: pointer; }
.prompt-clock:focus-visible { outline: 1px solid var(--ink); outline-offset: 3px; }

/* DOS section labels (see retro.js): the plain text stays for screen readers; the command line is visual */
.section-label.has-dos-label { position: relative; }

.dl-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.dos-label {
  display: block;
  white-space: nowrap;
  visibility: hidden;
}

.dos-label.is-shown { visibility: visible; }
.dl-prompt { color: var(--pixel-text); }
.dl-cmd { color: var(--ink); }

/* Partner sequence: one name lit at a time (the hover colour), with hard cuts */
.partner-name.is-lit { color: var(--pixel-text); }

/* Hidden DOS terminal */
.dos-term-overlay {
  position: fixed;
  inset: 0;
  z-index: 9990;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 12vh 16px 16px;
  background: rgba(14, 14, 14, 0.2);
}

.dos-term-overlay[hidden] { display: none; }
.dos-term-overlay.is-open .dos-term { animation: dos-open 120ms steps(1, end) both; }
.dos-term-overlay.is-closing .dos-term { animation: dos-close 120ms steps(1, end) both; }

.dos-term {
  width: min(640px, 100%);
  padding: 4px;
  background: var(--pixel);
  color: var(--on-pixel);
  box-shadow: 8px 8px 0 var(--ink);
  font-family: 'VT323', var(--mono);
  font-size: 20px;
  line-height: 1.15;
}

.dos-term-frame { border: 4px double var(--on-pixel); }

.dos-term-title {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--paper);
  color: var(--pixel-text);
  padding: 0 8px;
}

.dos-term-close {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

.dos-term-close:focus-visible { outline: 2px solid var(--pixel-text); outline-offset: 1px; }

.dos-term-screen {
  height: min(360px, 50vh);
  overflow-y: auto;
  padding: 8px 12px 12px;
}

.dos-term-output div,
.dos-term-line {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  min-height: 1.15em;
}

.dos-term-line { position: relative; }

/* The real input covers the line invisibly; the visible text mirrors it */
.dos-term-input {
  position: absolute;
  inset: 0;
  width: 100%;
  opacity: 0;
  border: 0;
  padding: 0;
  background: transparent;
  color: transparent;
  font: inherit;
  font-size: 20px;
}

/* ROCKS.EXE: while the game runs, it replaces the terminal's text screen */
.dos-term-overlay.is-game .dos-term { width: auto; max-width: 100%; }
.dos-term-overlay.is-game .dos-term-screen { height: auto; overflow: hidden; padding: 10px; }
.dos-term-overlay.is-game .dos-term-output,
.dos-term-overlay.is-game .dos-term-line { display: none; }

.dos-term-game[hidden] { display: none; }
.dos-term-game:focus { outline: none; }

.rocks-canvas {
  display: block;
  margin: 0 auto;
  image-rendering: pixelated;
}

/* Touch controls (rocks.js adds them, and .is-touch, only on touch screens). Upright: the screen,
   then the two button groups along the bottom for thumbs. Sideways: the groups flank the screen. */
.dos-term-game.is-touch {
  display: grid;
  grid-template: "canvas canvas" auto "note note" auto "left right" 1fr / auto auto;
  justify-content: space-between;
  align-items: end;
  gap: 8px;
  height: 100%;
  /* Buttons narrow a little on small phones so both groups fit under the screen (never below 48px) */
  --rocks-key: clamp(48px, 14.5vw, 56px);
}

.dos-term-game.is-touch[hidden] { display: none; }
.dos-term-game.is-touch .rocks-canvas {
  grid-area: canvas;
  outline: 1px solid var(--on-pixel); /* the playfield's edge, where things wrap */
}
.rocks-pad { display: contents; }

.rocks-rotate {
  grid-area: note;
  display: none;
  justify-self: center;
  font-family: 'Silkscreen', var(--mono);
  font-size: 10px;
  text-transform: uppercase;
  text-align: center;
}

.rocks-rotate::before { content: '\21BB  '; }
.wants-rotate .rocks-rotate { display: block; }

.rocks-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.rocks-left { grid-area: left; justify-self: start; align-items: flex-start; }
.rocks-right { grid-area: right; justify-self: end; align-items: flex-end; }
.rocks-keys { display: flex; gap: min(6px, 1.5vw); }

.rocks-button {
  display: grid;
  place-items: center;
  align-content: center;
  gap: 4px;
  width: var(--rocks-key, 56px);
  height: 56px;
  padding: 0;
  font-family: 'Silkscreen', var(--mono);
  font-size: 8px;
  line-height: 1;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--ink);
  border-radius: 0;
  box-shadow: 2px 2px 0 var(--ink);
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}

.rocks-button svg { display: block; }
.rocks-key-fire { width: calc(var(--rocks-key, 56px) + 12px); }
.rocks-button.rocks-aux { width: auto; height: 44px; padding: 0 12px; }

.rocks-button.is-down {
  translate: 2px 2px;
  box-shadow: none;
}

@media (orientation: landscape) {
  .dos-term-game.is-touch {
    grid-template: "left canvas right" 1fr / 1fr auto 1fr;
    justify-content: stretch;
    gap: 0 12px;
  }
  .dos-term-game.is-touch .rocks-canvas { align-self: center; }
  .wants-rotate .rocks-rotate { display: none; }
  .rocks-group { height: 100%; justify-content: space-between; }
  /* Sideways, thrust sits over the two turn buttons, and hyperspace over fire */
  .rocks-left .rocks-keys { display: grid; grid-template-columns: var(--rocks-key) var(--rocks-key); }
  .rocks-left .rocks-key-thrust { grid-row: 1; grid-column: 1 / -1; width: 100%; }
  .rocks-right .rocks-keys { flex-direction: column; align-items: flex-end; }
}

.dos-term-announce {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .block-cursor,
  .dos-term-overlay.is-open .dos-term,
  .dos-term-overlay.is-closing .dos-term { animation: none; }
}

/* Work preview card (fine pointers only; element added by JS) */
.work-card {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 9997;
  display: none;
  pointer-events: none;
  padding: 3px;
  background: var(--pixel);
  box-shadow: 6px 6px 0 var(--ink);
}

.work-card.is-open,
.work-card.is-closing { display: block; }
.work-card.is-open { animation: dos-open 120ms steps(1, end) both; }
.work-card.is-closing { animation: dos-close 120ms steps(1, end) both; }

/* After the rules above, or they'd win: reduced motion opens and closes the card instantly */
@media (prefers-reduced-motion: reduce) {
  .work-card.is-open,
  .work-card.is-closing { animation: none; }
}

.work-card-bar {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 4px 5px 5px;
  font-family: 'Silkscreen', var(--mono);
  font-size: 8px;
  line-height: 1;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--on-pixel);
}

.work-card-media {
  position: relative;
  width: 320px;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--pixel);
}

.work-card-media img,
.work-card-media canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.work-card-media img { object-fit: cover; }
.work-card-media canvas { image-rendering: pixelated; }
.work-card-media canvas[hidden] { display: none; }

/* No usable media: a cobalt card with the client name in the pixel font */
.work-card-fallback {
  position: absolute;
  inset: 0;
  display: none;
  place-items: center;
  font-family: 'Silkscreen', var(--mono);
  font-size: 16px;
  text-transform: uppercase;
  color: var(--on-pixel);
}

.work-card.is-missing .work-card-fallback { display: grid; }
.work-card.is-missing img { visibility: hidden; }

/* The featured row's zoom entrance: ink outlines stepping from its thumbnail to the card (added by JS) */
.work-zoom {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 9997;
  pointer-events: none;
  border: 1px solid var(--ink);
}

.work-zoom[hidden] { display: none; }

/* Collapsible work list: hidden rows are gone entirely; the button sits under the rows' column */
.work-item[hidden] { display: none; }
.work-more {
  grid-column: -2 / -1;
  margin-top: 24px;
}

/* Letter-grid pixel icons (see gridSvg in retro.js) */
.g-I { fill: var(--ink); }
.g-P { fill: var(--pixel); }
.g-C { fill: currentColor; }
.g-Q { fill: var(--pixel-hi); }
.g-S { fill: var(--pixel-lo); }
/* Shaded greys and white: fixed in every theme */
.g-E { fill: #262523; }
.g-D { fill: #3d3c3a; }
.g-M { fill: #8d8a84; }
.g-L { fill: #d7d3ca; }
.g-W { fill: #fbfaf6; }
/* Food stays food in every theme */
.g-K { fill: #c98a3e; }
.g-Y { fill: #f2c14e; }
.g-R { fill: #c52e13; }

/* Two-frame icons: frames stack; the second hides until its item is active */
.dos-button-icon svg { grid-area: 1 / 1; }
.dos-button-icon svg + svg { visibility: hidden; }

/* Core expertise readout panel (JS replaces the plain description list with it) */
.expertise.xp-ready .expertise-details { display: none; }

.xp-panel {
  position: relative;
  margin-top: 20px;
  padding: 12px 14px;
  border: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.7;
  color: #555;
  overflow: hidden;
}

.xp-prompt {
  color: var(--ink);
  letter-spacing: 0.06em;
}

.xp-pinned {
  margin-left: 10px;
  color: var(--pixel-text);
  letter-spacing: 0.1em;
}

.xp-hint {
  margin-left: 14px;
  color: var(--mid);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-size: 10px;
}

.xp-see {
  margin-top: 6px;
  color: var(--ink);
  letter-spacing: 0.06em;
}

.xp-see a {
  color: var(--pixel-text);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
}

/* Screen-reader copy of the full description; the typed text is aria-hidden */
.xp-announce {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* DOS buttons: hero CTA, contact submit, /vibe gate */
.dos-button {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 11px 18px;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--ink);
  border-radius: 0;
  box-shadow: 3px 3px 0 var(--ink);
  cursor: pointer;
}

.dos-button:hover {
  color: var(--on-pixel);
  background: var(--pixel);
}

/* Pressed: the key goes down into its shadow, then springs back */
.dos-button:active,
.dos-button.is-pressed {
  translate: 3px 3px;
  box-shadow: none;
}

.dos-button:focus-visible {
  outline: 2px solid var(--pixel-text);
  outline-offset: 4px;
}

.dos-button:disabled { cursor: default; }

.dos-button-icon { display: inline-grid; }
.dos-button-icon:empty { display: none; }

.dos-button-cursor { display: none; }
.dos-button:hover .dos-button-cursor { display: inline-block; margin-left: -4px; }

/* Hover opens the envelope (or nudges the enter arrow): frame one, then frame two, and hold */
.dos-button:hover .dos-button-icon svg:first-child { animation: flap-first 160ms steps(1, end) forwards; }
.dos-button:hover .dos-button-icon svg + svg { animation: flap-second 160ms steps(1, end) forwards; }

@keyframes flap-first {
  0%        { visibility: visible; }
  50%, 100% { visibility: hidden; }
}

@keyframes flap-second {
  0%        { visibility: hidden; }
  50%, 100% { visibility: visible; }
}

/* Click effects (fine pointers only; pooled elements added by JS) */
.fx-bit,
.fx-word {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 9998;
  pointer-events: none;
  opacity: 0;
}

.fx-word {
  font-family: 'Silkscreen', var(--mono);
  font-size: 16px;
  line-height: 1;
  color: var(--pixel);
  text-shadow: 1px 1px 0 var(--ink);
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .dos-button:hover .dos-button-icon svg { animation: none; }
}

/* ── Touch screens (phones and tablets): none of this reaches a mouse and keyboard ── */

/* Work thumbnails (retro.js adds them on touch): the case study image, resolved through the mosaic */
.work-thumb {
  position: relative;
  width: 64px;
  height: 64px;
  overflow: hidden;
  background: var(--pixel);
}

.work-thumb img,
.work-thumb canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.work-thumb img { object-fit: cover; }
.work-thumb img:not([src]) { visibility: hidden; }
.work-thumb canvas { image-rendering: pixelated; }
.work-thumb canvas[hidden] { display: none; }

.work-list.has-thumbs .work-item {
  grid-template-columns: 64px 1fr auto;
  column-gap: 16px;
  align-items: center;
}

/* Expertise inline (touch screens and narrow windows): one column, the readout under the open skill */
.expertise.xp-inline .expertise-list { grid-template-columns: 1fr; }
.expertise.xp-inline .expertise-list li { padding-right: 0; }
.expertise.xp-inline .xp-panel {
  margin: 0 0 12px;
  font-size: 12px;
}
.expertise.xp-inline .xp-panel[hidden] { display: none; }

/* A DOS tree marker says each skill opens and closes */
.expertise.xp-inline .expertise-item::after {
  content: '[+]';
  content: '[+]' / '';
  margin-left: auto;
  padding-left: 12px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--mid);
}

.expertise.xp-inline .expertise-item[aria-expanded="true"]::after {
  content: '[-]';
  content: '[-]' / '';
  color: var(--pixel-text);
}

/* Terminal command keys (touch only) */
.dos-term-keys {
  display: flex;
  gap: 6px;
  padding: 8px 12px 0;
}

.dos-term-key {
  flex: 1 1 auto;
  min-height: 44px;
  padding: 0 4px;
  font: inherit;
  font-size: 18px;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--ink);
  border-radius: 0;
  box-shadow: 2px 2px 0 var(--ink);
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.dos-term-key:active { translate: 2px 2px; box-shadow: none; }
.dos-term-key:focus-visible { outline: 2px solid var(--on-pixel); outline-offset: 2px; }

/* Under the keys, the prompt line keeps the screen's side padding */
.dos-term-frame > .dos-term-line { margin: 8px 12px 10px; }
.dos-term-overlay.is-game .dos-term-keys { display: none; }

/* While the terminal is open on touch, the page behind is pinned (retro.js sets body's top) */
html.term-locked { overflow: hidden; overscroll-behavior: none; }
html.term-locked body {
  position: fixed;
  left: 0;
  right: 0;
  overflow: hidden;
}

@media (hover: none) and (pointer: coarse) {
  /* The terminal fits the visible area (above the keyboard, inside notches), and shrinks its screen */
  .dos-term-overlay {
    padding: max(12px, env(safe-area-inset-top)) max(8px, env(safe-area-inset-right))
      max(12px, env(safe-area-inset-bottom)) max(8px, env(safe-area-inset-left));
    overscroll-behavior: contain;
    touch-action: none;
  }

  .dos-term-overlay.is-fit {
    top: var(--vv-top, 0px);
    bottom: auto;
    height: var(--vv-height, 100%);
  }

  .dos-term {
    display: flex;
    flex-direction: column;
    max-height: 100%;
  }

  .dos-term-frame {
    display: flex;
    flex-direction: column;
    flex: 0 1 auto;
    min-height: 0;
  }

  .dos-term-screen {
    flex: 0 1 auto;
    min-height: 3.5em;
    overscroll-behavior: contain;
    touch-action: pan-y;
  }

  .dos-term-close { min-width: 44px; min-height: 44px; text-align: left; }

  /* ROCKS.EXE takes the whole visible area, like a handheld: no scrolling, zooming or selecting */
  .dos-term-overlay.is-game {
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
  }
  .dos-term-overlay.is-game .dos-term { width: 100%; height: 100%; }
  .dos-term-overlay.is-game .dos-term-frame { flex: 1 1 auto; }
  .dos-term-overlay.is-game .dos-term-screen { flex: 1 1 auto; padding: 6px; touch-action: none; }

  /* Hover doesn't exist here, so a tap mustn't leave hover styles stuck on */
  .dos-button:hover { color: var(--ink); background: var(--paper); }
  .dos-button:hover .dos-button-cursor { display: none; }
  .dos-button:hover .dos-button-icon svg:first-child,
  .dos-button:hover .dos-button-icon svg + svg { animation: none; }
  .dos-button { min-height: 44px; touch-action: manipulation; }

  .expertise-item:hover:not(.is-selected) .expertise-name { color: var(--ink); }

  /* Taps on the clock land even a little off it (the hit area grows; the layout doesn't) */
  .prompt-clock {
    position: relative;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
  }
  .prompt-clock::after {
    content: '';
    position: absolute;
    inset: -14px -10px;
  }
}

/* ── Contact form send sequence (retro.js) ── */

/* Validation: a DOS error line under the field, in the label style */
.form-error {
  padding: 0 0 12px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--pixel-text);
}

.form-error[hidden] { display: none; }

/* MAIL.EXE: the compose window's body turns into a terminal that prints the send, line by line.
   contact.js sizes it to the form it replaces, and the window's title bar names it. */
.contact-form[hidden] { display: none; }

.mail-panel {
  display: flex;
  flex-direction: column;
  padding: 4px;
  background: var(--pixel);
  color: var(--on-pixel);
  font-family: 'VT323', var(--mono);
  font-size: 20px;
  line-height: 1.15;
}

.mail-panel[hidden] { display: none; }
.mail-frame { flex: 1; border: 4px double var(--on-pixel); }

.mail-screen {
  min-height: 12.5em;
  padding: 8px 12px 14px;
}

.mail-screen .mail-line {
  min-height: 1.15em;
  max-width: none;
  margin: 0;
  font: inherit;
  color: inherit;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.mail-screen .mail-result:focus,
.mail-screen .mail-fallback:focus { outline: none; }
.mail-screen .mail-result:focus-visible,
.mail-screen .mail-fallback:focus-visible { outline: 1px dotted var(--on-pixel); outline-offset: 2px; }

/* While the service hasn't answered, a cursor blinks after the held bar */
.mail-bar.is-holding::after {
  content: '';
  display: inline-block;
  width: 0.5em;
  height: 1em;
  margin-left: 0.3em;
  vertical-align: -0.15em;
  background: currentColor;
  animation: block-blink 1s steps(1, end) infinite;
}

/* Bar cells: solid blocks when filled, a 2px dither when empty (the characters stay underneath) */
.mail-cells { display: inline-flex; vertical-align: -0.12em; }

.mail-cell {
  width: 0.5em;
  height: 1em;
  overflow: hidden;
  color: transparent;
  background: repeating-conic-gradient(var(--on-pixel) 0 25%, transparent 0 50%) 0 0 / 4px 4px;
}

.mail-cell.is-on { background: var(--on-pixel); }

.mail-fallback a { color: inherit; }

.mail-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 14px;
}

.mail-button { min-height: 44px; }
.mail-button:focus-visible { outline-color: var(--on-pixel); }

/* The envelope that flies off on success: paper body, ink lines */
.mail-envelope {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 9998;
  pointer-events: none;
  display: grid;
  background: var(--paper);
  color: var(--ink);
}

@media (max-width: 660px) {
  .mail-panel { font-size: 17px; }
  .mail-screen { padding: 8px 10px 14px; }
  .form-error { font-size: 11px; }
}

@media (prefers-reduced-motion: reduce) {
  .mail-bar.is-holding::after { animation: none; }
}

/* ── Footer: a DOS function key bar (Norton Commander's bottom row) and, on the homepage, the /vibe pizza ── */
.fkeys {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 14px;
}

.fkey {
  position: relative;
  display: inline-flex;
  align-items: center;
  padding: 0;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  background: none;
  border: 0;
  border-radius: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.fkey[hidden] { display: none; }

/* Phones: the same tightened tracking as the menu bar, so the two bars match */
@media (max-width: 660px) {
  .fkey { letter-spacing: 0.04em; }
}
.fkey-num { padding-right: 3px; }

/* The label is an inverted block; hover and focus flip it back to paper, with a hard cut */
.fkey-label {
  padding: 3px 5px 3px 6px;
  color: var(--on-pixel);
  background: var(--pixel);
  border: 1px solid var(--pixel);
}

.fkey:hover .fkey-label,
.fkey:focus-visible .fkey-label {
  color: var(--ink);
  background: var(--paper);
  border-color: var(--ink);
}

.fkey:focus { outline: none; }

.footer-vibe {
  position: relative;
  display: block;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--mid);
  -webkit-tap-highlight-color: transparent;
}

.footer-pizza { display: grid; }

/* C:\VIBE shows to the slice's left on hover or focus, out of the layout */
.footer-vibe-label {
  position: absolute;
  top: 50%;
  right: calc(100% + 10px);
  translate: 0 -50%;
  white-space: nowrap;
  visibility: hidden;
}

.footer-vibe:hover .footer-vibe-label,
.footer-vibe:focus-visible .footer-vibe-label { visibility: visible; }

.footer-vibe:hover .footer-pizza,
.footer-vibe:focus-visible .footer-pizza { animation: pixel-bob 0.5s steps(1, end) infinite; }

.footer-vibe:focus { outline: none; }
.footer-vibe:focus-visible { outline: 2px solid var(--pixel-text); outline-offset: 4px; }

/* Touch: 44px tap areas that don't move the layout, and no hover label */
@media (hover: none) and (pointer: coarse) {
  .fkey::after,
  .footer-vibe::after {
    content: '';
    position: absolute;
    inset: -13px -7px;
  }
  .footer-vibe::after { inset: -11px; }
  .footer-vibe-label { display: none; }
  .footer-vibe:hover .footer-pizza { animation: none; }
}

@media (prefers-reduced-motion: reduce) {
  .footer-vibe:hover .footer-pizza,
  .footer-vibe:focus-visible .footer-pizza { animation: none; }
}
