:root {
  --v2-bg: #070707;
  --v2-fg: #f4f3ef;
  --v2-dim: #aaa9a3;
  --v2-line: rgba(244, 243, 239, .72);
  --v2-soft-line: rgba(244, 243, 239, .2);
  --v2-panel: #151515;
  --v2-panel-raised: #202020;
  --v2-green: #1ed760;
  --v2-yellow: #f7c947;
  --v2-blue: #71c8ff;
}

/* Parwani-DOS redesign (docs/agent-rulebook.md §3, 2026-10-07): Pixelify Sans + a PixC override
   for its C/c (Pixelify's own C reads as an O), and four colour themes. Themes are scoped to
   .portfolio-v2 and alias the existing --v2-* tokens to the new --bg/--fg/--p1.../--ok/--warn
   set, so every component already wired to --v2-bg, --v2-panel etc. recolours with no changes
   of its own. "Mono" reproduces the old locked greyscale palette exactly. */
@font-face { font-family: 'PixC'; src: url('/assets/fonts/PixC-400.otf') format('opentype'); font-weight: 400 599; font-display: swap; unicode-range: U+0043, U+0063; }
@font-face { font-family: 'PixC'; src: url('/assets/fonts/PixC-700.otf') format('opentype'); font-weight: 600 900; font-display: swap; unicode-range: U+0043, U+0063; }

.portfolio-v2 {
  --display: 'PixC', 'Pixelify Sans', sans-serif;
  --mono: 'PixC', 'Pixelify Sans', sans-serif;
  --v2-bg: var(--bg);
  --v2-fg: var(--fg);
  --v2-dim: var(--dim);
  --v2-line: var(--line);
  --v2-soft-line: var(--line);
  --v2-panel: var(--p1);
  --v2-panel-raised: var(--p2);
  --v2-green: var(--ok);
  --v2-yellow: var(--warn);
}
.portfolio-v2, .portfolio-v2[data-theme="night"] {
  --bg: #0d1020; --fg: #f3ead8; --p0: #10142a; --p1: #151a33; --p2: #1d2346; --p3: #262d57;
  --dim: #9a9db8; --line: rgba(243, 234, 216, .2); --ok: #7ef0b0; --warn: #ffc65c; --on: #0d1020;
}
.portfolio-v2[data-theme="mono"] {
  --bg: #070707; --fg: #f4f3ef; --p0: #0d0d0d; --p1: #151515; --p2: #202020; --p3: #262626;
  --dim: #aaa9a3; --line: rgba(244, 243, 239, .2); --ok: #1ed760; --warn: #f7c947; --on: #070707;
}
.portfolio-v2[data-theme="paper"] {
  --bg: #ecebe4; --fg: #141414; --p0: #e3e1d9; --p1: #dcdad1; --p2: #d0cec4; --p3: #c6c4b9;
  --dim: #55534c; --line: rgba(20, 20, 20, .18); --ok: #2fbf63; --warn: #e0a526; --on: #141414;
  /* Accessibility pass (Phase 9): Paper's --ok/--warn are fill colours; as text on its light panels
     they fall to 1.4-1.7:1, so status text uses darker variants (>= 4.9:1 on --p2). --dim is a
     shade darker than the mockup's #5c5a53 for the same reason (4.37:1 on --p2 before). */
  --v2-green: #1d5e33; --v2-yellow: #6b4700;
}

#boot { display: none !important; }
body.locked { overflow: auto !important; height: auto !important; }

#site > .site-header,
#site > .nav-float,
#site > .gig-fab,
#site > .gig-scrim,
#site > .gig-rail,
#site > audio,
#site > main { display: none !important; }

.portfolio-v2 {
  min-height: 100vh;
  background: var(--v2-bg);
  color: var(--v2-fg);
  font-family: var(--mono);
  padding: 1.2rem clamp(.75rem, 2.1vw, 2.25rem) 1rem;
}

/* Parwani-DOS top bar: brand + theme switcher left, typed command line centre, section
   counter + clock right. Three-column grid so the centre command line stays truly centred. */
.v2-nav {
  position: sticky;
  top: 0;
  z-index: 50;
  min-height: 40px;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1rem;
  border-bottom: 1px solid var(--v2-soft-line);
  background: var(--v2-bg);
  padding: 0 .9rem;
  font-size: .78rem;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.pdos-left { display: flex; align-items: center; gap: .5rem; min-width: 0; }
.pdos-brand { flex: 0 0 auto; padding: .3rem .4rem; font-weight: 700; white-space: nowrap; }
.pdos-brand:hover, .pdos-brand:focus-visible { background: var(--v2-fg); color: var(--on); text-decoration: none; }

.pdos-theme { position: relative; flex: 0 0 auto; }
.pdos-theme-btn {
  display: flex; align-items: center; gap: .5rem; padding: .3rem .55rem;
  border: 1px solid var(--v2-soft-line); background: none; color: var(--v2-fg);
  font: inherit; letter-spacing: inherit; text-transform: inherit; cursor: pointer; white-space: nowrap;
}
.pdos-theme-btn:hover, .pdos-theme-btn:focus-visible, .pdos-theme-btn[aria-expanded="true"] { background: var(--v2-fg); color: var(--on); }
.pdos-swatch { display: flex; flex: 0 0 auto; }
.pdos-swatch span { display: block; width: .45em; height: .85em; }
.pdos-swatch span:first-child { outline: 1px solid var(--v2-soft-line); outline-offset: -1px; }
.pdos-theme-menu {
  position: absolute; left: 0; top: calc(100% + 6px); z-index: 60; width: 220px;
  display: flex; flex-direction: column; padding: 4px;
  background: var(--v2-panel); border: 1px solid var(--v2-fg); box-shadow: 8px 8px 0 rgba(0, 0, 0, .45);
}
/* Same specificity as the UA [hidden]{display:none} rule, so the author rule above would
   otherwise win on source order alone and the menu could never actually hide. */
.pdos-theme-menu[hidden] { display: none; }
.pdos-theme-opt {
  display: flex; align-items: center; gap: .65rem; padding: .55rem .6rem; width: 100%;
  border: 0; background: none; color: var(--v2-fg); font: inherit; letter-spacing: inherit;
  text-transform: inherit; text-align: left; cursor: pointer;
}
.pdos-theme-opt:hover, .pdos-theme-opt:focus-visible { background: var(--v2-panel-raised); }
.pdos-theme-opt[aria-selected="true"] { background: var(--v2-panel-raised); }
.pdos-theme-opt-label { flex: 1 1 auto; }
.pdos-theme-opt-mark { flex: 0 0 auto; }

.pdos-cmd { min-width: 0; white-space: nowrap; text-transform: none; letter-spacing: .02em; }

.pdos-right { display: flex; justify-content: flex-end; gap: 1rem; min-width: 0; color: var(--v2-dim); white-space: nowrap; overflow: hidden; }
.pdos-right span:first-child { color: var(--v2-fg); }

.v2-cursor {
  display: inline-block;
  width: .6em;
  height: 1em;
  margin-left: .15em;
  vertical-align: -.15em;
  background: var(--v2-fg);
  animation: blink 1s steps(1) infinite;
}

.v2-section { width: 100%; margin: 0 auto; padding: .7rem 0 1.1rem; scroll-margin-top: 52px; }
.v2-section + .v2-section { border-top: 1px solid var(--v2-line); }
.v2-section-head { margin-bottom: .65rem; }
.v2-ref { display: block; font-size: clamp(.68rem, 1.45vh, .9rem); color: var(--v2-fg); letter-spacing: .06em; text-transform: uppercase; }
.v2-display {
  margin: .25rem 0 1.2rem;
  font-family: var(--display);
  font-weight: 400;
  text-transform: uppercase;
  line-height: 1;
  letter-spacing: -.025em;
  white-space: nowrap;
  font-size: 12vw;
}
.v2-section-title {
  margin: .18rem 0 .55rem;
  font-family: var(--display);
  font-weight: 400;
  text-transform: uppercase;
  line-height: .88;
  font-size: clamp(3.7rem, 6.2vw, 7rem);
}
.v2-section-kicker { margin: 0 0 .8rem; color: var(--v2-fg); font-size: .9rem; letter-spacing: .16em; text-transform: uppercase; }

.v2-panel { border: 0; background: var(--v2-panel); }
.v2-index-row { display: flex; align-items: center; justify-content: space-between; gap: 1rem; font-size: .66rem; text-transform: uppercase; letter-spacing: .04em; }
.v2-tag { color: var(--v2-dim); }

.v2-scroll-next { display: flex; align-items: center; justify-content: center; gap: 1rem; margin-top: .85rem; color: var(--v2-fg); font-size: clamp(.66rem, 1.45vh, .86rem); letter-spacing: .04em; text-align: center; text-transform: uppercase; white-space: nowrap; }
.v2-scroll-next span { height: 1px; flex: 1; background: var(--v2-soft-line); }
.v2-scroll-next:hover { color: var(--v2-yellow); }

/* Parwani-DOS Home (Phase 2, 2026-10-07): a title + about.txt row, a 3x2 grid of tiles that
   jump to each section (pixel icons land in Phase 8 — .pdos-tile-icon is reserved empty space
   for now), an extras row, and a right-hand column of small "window" widgets wired to the same
   Worker endpoints as before (every #id and data-bound class below is unchanged from the old
   dashboard, so none of the fetch/render JS needed to change — only the surrounding markup). */
.pdos-home { flex: 1 1 auto; min-height: 0; display: grid; grid-template-columns: minmax(0, 1fr) minmax(220px, 330px); gap: 10px; }
.pdos-home-left { min-width: 0; min-height: 0; display: grid; grid-template-rows: auto minmax(0, 1fr) auto; gap: 10px; }
.pdos-home-right { min-width: 0; min-height: 0; display: grid; grid-template-rows: auto auto auto minmax(0, 1fr) auto auto; gap: 8px; }

.pdos-title-row { display: grid; grid-template-columns: minmax(0, 1fr) clamp(180px, 30%, 380px); gap: 10px; align-items: stretch; }
.pdos-title-cell { min-width: 0; display: flex; align-items: flex-end; overflow: hidden; }
/* The title spans its whole cell so fitPortfolioTitle() fits the widest line to the cell, not to itself. */
.pdos-title-cell .v2-display { flex: 1 1 auto; min-width: 0; }
/* Title size: the widest line fills the cell. In Pixelify Sans "PORTFOLIO." is 5.07em wide, so
   19.5cqw fills the cell. Capped by height (two lines) so the tiles keep their room, lower on
   short screens so the tile icons stay visible. Pure CSS so the LCP element paints at its final
   size without waiting for script. */
@media (min-width: 721px) {
  .pdos-title-cell { container-type: inline-size; }
  .pdos-title-cell .v2-display { font-size: min(19.5cqw, 23.5vh, 340px); }
}
@media (min-width: 721px) and (max-height: 799px) {
  .pdos-title-cell .v2-display { font-size: min(19.5cqw, 15vh, 340px); }
}
.v2-display { margin: 0; font-family: var(--display); font-weight: 400; text-transform: uppercase; line-height: 1.02; letter-spacing: -.02em; white-space: nowrap; font-size: 12vw; }

/* Generic "window": a filled title bar (filename + index) over a flat body. Every Home widget
   shares this shell; #ids inside keep working exactly as before. */
.pdos-widget { min-width: 0; min-height: 0; display: flex; flex-direction: column; }
.pdos-widget-head { flex: 0 0 auto; height: 26px; background: var(--v2-panel-raised); display: flex; align-items: center; justify-content: space-between; padding: 0 .6rem; font-size: .66rem; letter-spacing: .04em; text-transform: uppercase; }
.pdos-widget-tag { color: var(--v2-dim); }
.pdos-widget-tag--warn { color: var(--v2-yellow); }
.pdos-widget-body { flex: 1 1 auto; min-height: 0; background: var(--v2-panel); padding: clamp(.55rem, 1.4vh, .85rem) clamp(.6rem, 1vw, .8rem); display: flex; flex-direction: column; overflow: hidden; }
.pdos-widget-foot { flex: 0 0 auto; background: var(--v2-panel); padding: 0 clamp(.6rem, 1vw, .8rem) clamp(.4rem, 1vh, .6rem); color: var(--v2-dim); font-size: clamp(.54rem, 1.2vh, .68rem); text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pdos-widget-label { color: var(--v2-dim); font-size: .66rem; text-transform: uppercase; }

.pdos-about-body p { margin: auto 0; max-width: 24ch; font-size: clamp(.78rem, min(1.3vw, 2.3vh), 1.2rem); line-height: 1.45; }
.pdos-boot-log { display: flex; flex-direction: column; gap: .15rem; margin-top: .5rem; padding-top: .5rem; border-top: 1px solid var(--v2-soft-line); color: var(--v2-dim); font-size: .62rem; line-height: 1.6; text-transform: none; letter-spacing: 0; }
.pdos-ok { color: var(--v2-green); }
.pdos-warn { color: var(--v2-yellow); }
.v2-about-date { flex: 0 0 auto; margin-top: .5rem; color: var(--v2-dim); font-size: clamp(.54rem, 1.25vh, .7rem); letter-spacing: .05em; text-transform: uppercase; }

/* Six tiles jump straight to their section; hover fills the tile with its colour (spec table). */
.pdos-tiles { min-height: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-rows: repeat(2, minmax(0, 1fr)); gap: 8px; }
.pdos-tile {
  min-width: 0; min-height: 0; overflow: hidden; display: flex; flex-direction: column;
  background: var(--v2-panel); color: var(--v2-fg); padding: clamp(.6rem, 1.4vh, .85rem); cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.pdos-tile-head { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: .5rem; font-size: .66rem; text-transform: uppercase; letter-spacing: .03em; }
.pdos-tile-head > span:nth-child(2) { flex: 1 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.pdos-tile-glyph { flex: 0 0 auto; width: .85em; height: .85em; background: currentColor; }
.pdos-tile-glyph--round { border-radius: 50%; }
.pdos-tile-glyph--diamond { transform: rotate(45deg); width: .6em; height: .6em; margin: .12em; }
.pdos-tile-glyph--ring { border-radius: 50%; border: 3px solid currentColor; background: none; box-sizing: border-box; }
.pdos-tile-glyph--frame { border: 2px solid currentColor; background: none; box-sizing: border-box; }
.pdos-tile-glyph--bars { flex: 0 0 auto; display: flex; gap: 2px; width: auto; height: .85em; }
.pdos-tile-glyph--bars span { display: block; width: 4px; height: 100%; background: currentColor; }
.pdos-tile-key { flex: 0 0 auto; border: 1px solid currentColor; padding: 0 .35rem; }
.pdos-tile-title { flex: 0 0 auto; margin-top: .5rem; font-family: var(--display); font-weight: 400; font-size: clamp(1.3rem, min(2.4vw, 4.6vh), 2.1rem); text-transform: uppercase; line-height: 1; }
.pdos-tile-icon { flex: 1 1 auto; min-height: 0; }
.pdos-tile-foot { flex: 0 0 auto; margin-top: auto; padding-top: clamp(.4rem, 1vh, .6rem); border-top: 1px solid currentColor; display: flex; flex-direction: column; gap: .15rem; font-size: .7rem; line-height: 1.3; }
.pdos-tile-foot > span:first-child { font-size: .62rem; text-transform: uppercase; opacity: .7; }
.pdos-tile-foot > span:last-child { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pdos-tile--journal:hover, .pdos-tile--journal:focus-visible { background: oklch(0.75 0.16 40); color: var(--on); }
.pdos-tile--projects:hover, .pdos-tile--projects:focus-visible { background: oklch(0.72 0.16 290); color: var(--on); }
.pdos-tile--toolbox:hover, .pdos-tile--toolbox:focus-visible { background: oklch(0.74 0.14 245); color: var(--on); }
.pdos-tile--media:hover, .pdos-tile--media:focus-visible { background: oklch(0.74 0.16 0); color: var(--on); }
.pdos-tile--playlists:hover, .pdos-tile--playlists:focus-visible { background: var(--ok); color: var(--on); }
.pdos-tile--gigs:hover, .pdos-tile--gigs:focus-visible { background: #160a06; color: #ffd43b; }

/* Extras: Champion Run and Crack, both jump to Projects (the windows themselves are Phase 4/5). */
.pdos-extras { flex: 0 0 auto; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; font-size: .72rem; text-transform: uppercase; letter-spacing: .04em; }
.pdos-extra { display: flex; align-items: center; justify-content: space-between; gap: .75rem; padding: 4px .85rem; border: 1px solid var(--v2-soft-line); color: var(--v2-fg); transition: border-color .15s ease, color .15s ease; }
.pdos-extra > span:first-of-type { display: flex; align-items: center; gap: .75rem; min-width: 0; }
.pdos-extra-icon { flex: 0 0 auto; display: flex; align-items: center; }
.pdos-extra > span:nth-of-type(2) { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pdos-extra-label { color: var(--v2-dim); }
.pdos-extra--champion:hover, .pdos-extra--champion:focus-visible { border-color: var(--warn); color: var(--warn); }
.pdos-extra--crack:hover, .pdos-extra--crack:focus-visible { border-color: var(--ok); color: var(--ok); }

/* Right column widgets — ids/classes below this point are the same ones the fetch functions in
   ui-v2.js already target; only their container markup changed. */
/* Widgets in the right column sit in auto-height grid rows, so none of them may use
   container-type: size (size containment gives the box zero intrinsic height and it collapses). */
.pdos-weather-body { flex-direction: row; align-items: center; justify-content: space-between; gap: .6rem; }
.pdos-weather .v2-value { font-size: clamp(1.6rem, min(3vw, 5vh), 2.4rem); }
.pdos-weather .v2-metric-foot { display: flex; flex-wrap: wrap; column-gap: .9em; }
/* Short screens: drop the humidity/wind line so the headlines window keeps its room. */
@media (max-height: 860px) { #v2WeatherExtras { display: none; } }
.v2-value { margin: .05rem 0; font-family: var(--display); font-size: clamp(2.1rem, min(4.4vw, 8.6vh), 5.25rem); line-height: 1.08; white-space: nowrap; }
.v2-value small { font-size: .42em; }
.v2-placeholder { color: var(--v2-dim); }
.v2-metric-foot { margin: 0; color: var(--v2-dim); font-size: clamp(.54rem, 1.25vh, .7rem); text-transform: uppercase; line-height: 1.45; }
.v2-metric-foot > span { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.v2-sun { width: clamp(24px, min(2.6vw, 5vh), 40px); height: clamp(24px, min(2.6vw, 5vh), 40px); color: var(--v2-yellow); flex: 0 0 auto; }

.pdos-spotify-body { flex-direction: row; align-items: center; gap: .7rem; }
.v2-spotify-art { flex: 0 0 auto; width: 48px; }
.v2-spotify-cover { width: 100%; aspect-ratio: 1; object-fit: cover; display: block; background: var(--v2-panel-raised); }
.pdos-spotify-text { min-width: 0; }
#v2NowTitle { margin: 0; max-width: 100%; font-family: var(--display); font-weight: 400; font-size: clamp(.95rem, min(1.6vw, 3vh), 1.5rem); line-height: 1.05; text-transform: uppercase; }
.v2-spotify-label { color: var(--v2-green); }
.v2-spotify-state { max-width: 100%; margin-top: .15rem; font-size: clamp(.54rem, 1.25vh, .7rem); text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.v2-spotify-status:empty { display: none; }

.pdos-mini-grid { min-height: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.pdos-heart .v2-value, .pdos-heart .v2-metric-foot { margin-top: auto; }
/* Heart and steps share a ~160px column: their numbers size from the body's own width (cqw),
   so "180 BPM" and "10,000/10,000" always fit inside the window. */
.pdos-mini-grid .pdos-widget-body { container-type: inline-size; }
.pdos-mini-grid .v2-value { font-size: clamp(1.3rem, 34cqw, 3rem); }

/* Steps widget (Codex's oversized-count variant): small label, the count as large as the body's
   width allows with "/10,000" on its baseline, a progress line and the goal line. 19cqw keeps the
   widest case, "10,000/10,000" (about 4.9em), inside the body. */
.v2-steps-label { margin-top: auto; color: var(--v2-dim); font-size: .62rem; letter-spacing: .08em; text-transform: uppercase; }
.v2-steps-value { margin: .3rem 0 .5rem; font-family: var(--display); font-size: clamp(1rem, 19cqw, 3rem); line-height: .9; white-space: nowrap; }
.v2-steps-value small { margin-left: .12em; font-size: .4em; }
.v2-steps-bar { flex: 0 0 auto; height: 3px; background: var(--v2-soft-line); }
.v2-steps-bar span { display: block; width: 0; height: 100%; background: var(--v2-fg); transition: width .6s ease; }
.v2-steps-goal { margin: .4rem 0 auto; color: var(--v2-dim); font-size: .62rem; letter-spacing: .08em; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.v2-steps--done .v2-steps-value, .v2-steps--done .v2-steps-goal { color: var(--v2-green); }
.v2-steps--done .v2-steps-bar span { background: var(--v2-green); }

.pdos-headlines { min-height: 0; }
.pdos-headlines-body { justify-content: center; gap: .5rem; }
/* fitHeadline() sizes both lines against this body, so neither may shrink or clamp on its own. */
.pdos-headlines-body h2 { flex: 0 0 auto; margin: 0; font-family: var(--display); font-weight: 400; font-size: clamp(1.4rem, min(3.2vw, 5.6vh), 2.6rem); line-height: 1.02; text-transform: uppercase; overflow-wrap: break-word; text-wrap: balance; }
.v2-news-desc { flex: 0 0 auto; margin: 0; color: var(--v2-fg); font-size: clamp(.6rem, 1.3vh, .76rem); line-height: 1.45; text-wrap: pretty; }

.pdos-game-body { flex-direction: row; align-items: center; gap: .6rem; }
.v2-game-art { flex: 0 0 auto; width: 40px; aspect-ratio: 1; object-fit: cover; display: block; background: var(--v2-panel-raised); }
.v2-game-art--portrait { aspect-ratio: 2 / 3; }
.v2-game-text { min-width: 0; }
.v2-game-text h3 { margin: 0; font-family: var(--display); font-weight: 400; font-size: clamp(.85rem, min(1.4vw, 2.6vh), 1.2rem); line-height: 1.05; text-transform: uppercase; }
.v2-game-text p { margin: .15rem 0 0; color: var(--v2-dim); font-size: .64rem; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.pdos-dissertation-body { flex-direction: row; align-items: flex-end; justify-content: space-between; gap: .6rem; }
.pdos-dissertation-body h3 { margin: 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--display); font-weight: 400; font-size: clamp(.85rem, min(1.5vw, 2.8vh), 1.25rem); line-height: 1.05; text-transform: uppercase; }
.pdos-dissertation-body a { flex: 0 0 auto; color: var(--v2-fg); font-size: .7rem; text-transform: uppercase; text-decoration: underline; text-underline-offset: .2em; }

.pdos-status-bar { flex: 0 0 auto; margin-top: auto; padding-top: clamp(.6rem, 2vh, 1.4rem); display: flex; align-items: center; justify-content: space-between; gap: 1rem; color: var(--v2-dim); font-size: .7rem; text-transform: uppercase; letter-spacing: .04em; }
.pdos-status-cmd { color: var(--v2-fg); white-space: nowrap; }

/* Fit-to-box titles (fitText in ui-v2.js): the CSS size is the maximum; long text shrinks
   until it fits its line budget (data-fit="1" one line, "2" wraps onto a second line). The
   clamp/ellipsis only shows if text is still too long at the minimum size. */
[data-fit] { overflow: hidden; }
[data-fit="1"] { white-space: nowrap; text-overflow: ellipsis; }
[data-fit="2"] { white-space: normal; overflow-wrap: break-word; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
[data-fit-max="3"] { -webkit-line-clamp: 3; }
[data-fit].is-fitting { display: block; -webkit-line-clamp: unset; text-overflow: clip; }

.v2-stage { display: flex; flex-direction: column; gap: 10px; min-height: 0; }
.v2-strip { flex: 0 0 auto; display: flex; flex-wrap: wrap; row-gap: .35rem; background: var(--v2-panel); padding: .75rem 1rem; font-size: .74rem; letter-spacing: .05em; text-transform: uppercase; }
.v2-strip span + span::before { content: '/'; margin: 0 1.3rem; color: var(--v2-dim); }

.v2-playlist, .v2-gig { transition: outline-color .15s ease; outline: 1px solid transparent; outline-offset: 3px; }
.v2-playlist:hover, .v2-gig:hover, .v2-playlist:focus-within, .v2-gig:focus-within { outline-color: var(--v2-soft-line); }

/* Card foot: hairline, status on the left, action on the right. Shared by projects and tools. */
.v2-card-foot { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-top: auto; padding-top: clamp(.45rem, 1.4vh, .85rem); border-top: 1px solid var(--v2-soft-line); font-size: clamp(.56rem, 1.25vh, .72rem); letter-spacing: .05em; text-transform: uppercase; }
.v2-card-foot > * { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.v2-card-foot a, .v2-card-foot button { padding: 0; border: 0; background: none; color: var(--v2-fg); font: inherit; letter-spacing: inherit; text-transform: inherit; cursor: pointer; }
.v2-card-foot a:hover, .v2-card-foot a:focus-visible, .v2-card-foot button:not(:disabled):hover, .v2-card-foot button:not(:disabled):focus-visible { text-decoration: underline; text-underline-offset: .3em; }
.v2-card-foot button:disabled { cursor: default; }

/* Window chrome (Parwani-DOS): a 30px title bar filled with the section's colour (--bar), text in
   --on, over a body with a 1px --line outline. Journal is the first section to use it; Projects,
   Toolbox and Media/Playlists/Gigs reuse it in later phases with their own --bar. */
.pdos-window { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; outline: 1px solid var(--v2-soft-line); }
.pdos-window--journal { --bar: oklch(0.75 0.16 40); }
.pdos-window-bar { flex: 0 0 auto; height: 30px; display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0 10px; background: var(--bar, var(--v2-panel-raised)); color: var(--on); font-size: .75rem; font-weight: 500; letter-spacing: .04em; text-transform: uppercase; white-space: nowrap; }
.pdos-window-bar > span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.pdos-window-nav { display: flex; gap: 14px; }
.pdos-window-nav a { color: inherit; }
.pdos-window-nav a:hover, .pdos-window-nav a:focus-visible { text-decoration: underline; text-underline-offset: .25em; }

/* Status colours shared by the journal list, meta rows and photo chips. */
.pdos-status--warn { color: var(--v2-yellow); }
.pdos-status--ok { color: var(--v2-green); }
.pdos-status--dim { color: var(--v2-dim); }

/* Journal (Phase 3): list of every entry on the left, the selected entry on the right. The list
   and the article body scroll inside the window; the page itself never does here. */
.pdos-journal { flex: 1 1 auto; min-height: 0; display: grid; grid-template-columns: clamp(290px, 31vw, 440px) minmax(0, 1fr); background: var(--v2-panel); }
.pdos-journal-side { min-width: 0; min-height: 0; display: flex; flex-direction: column; border-right: 1px solid var(--v2-soft-line); }
.pdos-journal-head { flex: 0 0 auto; display: flex; flex-direction: column; gap: 6px; padding: clamp(.6rem, 1.8vh, 1rem) 18px clamp(.5rem, 1.4vh, .75rem); }
.pdos-journal-title { margin: 0; font-family: var(--display); font-weight: 700; font-size: clamp(3rem, min(6.2vw, 11vh), 5.85rem); line-height: .86; text-transform: uppercase; white-space: nowrap; }
.pdos-journal-kicker { margin: 0; font-size: .75rem; letter-spacing: .1em; text-transform: uppercase; }
.pdos-journal-count, .pdos-journal-foot { flex: 0 0 auto; padding: 8px 18px; border-top: 1px solid var(--v2-soft-line); color: var(--v2-dim); font-size: .69rem; letter-spacing: .05em; text-transform: uppercase; }
.pdos-journal-foot { padding: 10px 18px; font-size: .62rem; line-height: 1.6; }
.pdos-journal-list { flex: 1 1 auto; min-height: 0; overflow: auto; }
.pdos-journal-row {
  width: 100%; display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 12px; align-items: start;
  padding: 12px 18px; border: 0; border-top: 1px solid var(--v2-soft-line); background: transparent; color: var(--v2-fg);
  font: inherit; text-align: left; cursor: pointer;
}
.pdos-journal-row:first-child { border-top: 0; }
.pdos-journal-row:hover { background: var(--v2-panel-raised); }
.pdos-journal-row:focus-visible { outline: 2px solid var(--bar); outline-offset: -2px; }
.pdos-journal-row[aria-selected="true"] { background: var(--v2-panel-raised); box-shadow: inset 3px 0 0 var(--bar); }
.pdos-journal-thumb { width: 64px; height: 64px; object-fit: cover; display: block; background: var(--v2-panel-raised); }
.pdos-journal-row-text { min-width: 0; display: flex; flex-direction: column; gap: 4px; font-size: .62rem; text-transform: uppercase; }
.pdos-journal-row-meta { display: flex; justify-content: space-between; gap: 8px; }
.pdos-journal-row-meta > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pdos-journal-row-meta > span:last-child { color: var(--v2-dim); }
.pdos-journal-row-title { font-family: var(--display); font-weight: 700; font-size: 1.375rem; line-height: 1; }

.pdos-journal-entry { min-width: 0; min-height: 0; display: flex; flex-direction: column; }
.pdos-journal-entry[hidden] { display: none; }
.pdos-journal-photo { flex: 0 0 auto; height: clamp(150px, 31vh, 280px); margin: 0; }
.pdos-journal-chip { position: absolute; z-index: 1; right: 14px; top: 12px; padding: 6px 10px; background: #070707; font-size: .69rem; letter-spacing: .05em; text-transform: uppercase; }
/* The chip is always black (it sits on a photo), so "Planned" cannot use the theme's --dim. */
.pdos-journal-chip.pdos-status--dim { color: #aaa9a3; }
.pdos-journal-chip.pdos-status--warn { color: #f7c947; }
.pdos-journal-chip.pdos-status--ok { color: #1ed760; }
.pdos-journal-score { --v2-score-size: clamp(84px, 15vh, 136px); position: absolute; z-index: 1; right: 18px; top: 14px; }
.pdos-journal-entry-head { flex: 0 0 auto; display: flex; flex-direction: column; gap: 8px; padding: 14px 22px 12px; border-bottom: 1px solid var(--v2-soft-line); }
.pdos-journal-entry-head h3 { margin: 0; font-family: var(--display); font-weight: 700; font-size: clamp(1.8rem, min(3.4vw, 6vh), 3rem); line-height: .95; text-transform: uppercase; }
.pdos-journal-meta { display: flex; flex-wrap: wrap; gap: 4px 16px; color: var(--v2-dim); font-size: .69rem; letter-spacing: .05em; text-transform: uppercase; }
.pdos-journal-article { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 18px 22px 40px; }
.pdos-journal-article:focus-visible { outline: 2px solid var(--bar); outline-offset: -2px; }
.pdos-journal-lead { margin: 0 0 16px; max-width: 68ch; font-size: 1rem; line-height: 1.6; text-wrap: pretty; }
.pdos-journal-note { margin: 0; color: var(--v2-dim); font-size: .69rem; letter-spacing: .06em; text-transform: uppercase; line-height: 1.6; }

/* Photo with a caption top-left over a dark gradient and its credit bottom-right (journal photos). */
.v2-journal-media { position: relative; min-height: 0; overflow: hidden; background: var(--v2-panel-raised); }
.v2-journal-media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.v2-journal-media::after { content: ''; position: absolute; inset: 0 0 auto; height: 4.5em; background: linear-gradient(rgba(0, 0, 0, .6), transparent); pointer-events: none; }
.v2-journal-media figcaption { position: absolute; z-index: 1; left: clamp(.6rem, 1vw, .9rem); top: clamp(.5rem, 1.4vh, .8rem); color: #f4f3ef; font-size: clamp(.56rem, 1.2vh, .7rem); letter-spacing: .05em; text-transform: uppercase; text-shadow: 0 1px 4px rgba(0, 0, 0, .9); }
/* Photo credit (Wikimedia Commons licences require attribution): bottom-right, quiet, links to the source page. */
.v2-journal-credit, .v2-gig-credit { position: absolute; z-index: 1; right: .45rem; bottom: .35rem; max-width: calc(100% - .9rem); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: rgba(244, 243, 239, .8); font-size: .62rem; letter-spacing: .03em; text-decoration: none; text-shadow: 0 1px 3px rgba(0, 0, 0, .95); }
.v2-journal-credit:hover, .v2-journal-credit:focus-visible, .v2-gig-credit:hover, .v2-gig-credit:focus-visible { color: #f4f3ef; text-decoration: underline; }
/* Review score: a jagged round badge (journal photos). */
.v2-score {
  --v2-score-size: clamp(64px, min(7vw, 13vh), 124px);
  width: var(--v2-score-size); height: var(--v2-score-size); flex: 0 0 auto;
  display: inline-flex; align-items: baseline; justify-content: center; padding-top: calc(var(--v2-score-size) * .26);
  color: #fff; font-family: var(--display); line-height: 1;
  clip-path: polygon(50% 0%, 56% 4.4%, 62.9% 1.7%, 67.6% 7.5%, 75% 6.7%, 78% 13.5%, 85.4% 14.6%, 86.5% 22%, 93.3% 25%, 92.5% 32.4%, 98.3% 37.1%, 95.6% 44%, 100% 50%, 95.6% 56%, 98.3% 62.9%, 92.5% 67.6%, 93.3% 75%, 86.5% 78%, 85.4% 85.4%, 78% 86.5%, 75% 93.3%, 67.6% 92.5%, 62.9% 98.3%, 56% 95.6%, 50% 100%, 44% 95.6%, 37.1% 98.3%, 32.4% 92.5%, 25% 93.3%, 22% 86.5%, 14.6% 85.4%, 13.5% 78%, 6.7% 75%, 7.5% 67.6%, 1.7% 62.9%, 4.4% 56%, 0% 50%, 4.4% 44%, 1.7% 37.1%, 7.5% 32.4%, 6.7% 25%, 13.5% 22%, 14.6% 14.6%, 22% 13.5%, 25% 6.7%, 32.4% 7.5%, 37.1% 1.7%, 44% 4.4%);
}
.v2-score b { font-weight: 400; font-size: calc(var(--v2-score-size) * .44); }
.v2-score small { margin-left: .15em; font-family: var(--mono); font-size: calc(var(--v2-score-size) * .11); }
.v2-score--red { background: #e5484d; }
.v2-score--yellow { background: var(--v2-yellow); color: #111; }
.v2-score--green { background: #1f9d55; }
.v2-score--purple { background: #5b21ff; }

/* Section windows (Phases 4-7): each section's title-bar colour. */
.pdos-window--projects { --bar: oklch(0.72 0.16 290); }
.pdos-window--toolbox { --bar: oklch(0.74 0.14 245); }
.pdos-window--media { --bar: oklch(0.74 0.16 0); }
.pdos-window--playlists { --bar: var(--ok); }
.pdos-window--gigs { --bar: oklch(0.86 0.15 95); }
.pdos-window-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 12px; padding: clamp(10px, 1.8vh, 16px); background: var(--v2-panel); }
.pdos-sec-head { flex: 0 0 auto; display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-end; gap: 12px 20px; }
/* Filter chips (Media: All / Films / Games, Gigs: Both / Dubai / Abu Dhabi). */
.pdos-filter { display: flex; gap: 4px; }
.pdos-filter button { padding: 8px 12px; border: 0; background: var(--v2-panel-raised); color: var(--v2-fg); font: inherit; font-size: .75rem; letter-spacing: .04em; text-transform: uppercase; cursor: pointer; }
.pdos-filter button:hover, .pdos-filter button:focus-visible { background: var(--bar); color: var(--on); }
.pdos-filter button:focus-visible { outline: 2px solid var(--v2-fg); outline-offset: 2px; }
.pdos-filter button[aria-pressed="true"] { background: var(--v2-fg); color: var(--v2-bg); }
.pdos-sec-title { margin: 0; font-family: var(--display); font-weight: 700; font-size: clamp(2.6rem, min(6.4vw, 10vh), 6.5rem); line-height: .86; text-transform: uppercase; }
.pdos-sec-kicker { margin: 6px 0 0; font-size: .75rem; letter-spacing: .12em; text-transform: uppercase; }
/* Cards inside a window body sit one step lighter than the body. */
.pdos-window-body .v2-panel, .pdos-window-body .v2-gig-controls, .pdos-window-body .v2-strip { background: var(--v2-panel-raised); }
.pdos-window-body .v2-gig-buttons { background: var(--v2-panel); }
.pdos-window-body .v2-gig:hover, .pdos-window-body .v2-gig:focus-within { outline-color: var(--bar); }
.pdos-chip { border: 1px solid currentColor; padding: 1px 6px; }

/* Pixel icons (pdos-icons.js). A fitted icon fills its box and its sprite is centred inside it
   without taking up layout space, so the box is sized by the card, never by the sprite. */
.pdos-icon { display: inline-flex; flex: 0 0 auto; }
.pdos-icon--fit { position: relative; display: block; width: 100%; height: 100%; }
.pdos-icon--fit > div { position: absolute !important; left: 50%; top: 50%; translate: -50% -50%; }
.pdos-icon:not(.is-on):not([data-icon="ball"]) *, .pdos-icon.is-offscreen * { animation-play-state: paused !important; }
.pdos-tile-icon { display: flex; align-items: center; justify-content: center; overflow: hidden; padding: 4px 0; }

/* Projects (Phase 4): six cards and the Champion Run cartridge; each opens a window. */
.pdos-projects { flex: 1 1 auto; min-height: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-rows: minmax(0, 1fr) minmax(0, 1fr) clamp(118px, 19vh, 168px); gap: 8px; padding: 12px; background: var(--p0); }
.pdos-project {
  text-decoration: none;
  min-width: 0; min-height: 0; overflow: hidden; display: flex; flex-direction: column; padding: clamp(10px, 1.6vh, 14px);
  border: 0; background: var(--v2-panel); color: var(--v2-fg); font: inherit; text-align: left; cursor: pointer;
  transition: background .15s, color .15s;
}
.pdos-project:focus-visible { outline: 2px solid var(--v2-fg); outline-offset: 2px; }
.pdos-project-head { flex: 0 0 auto; display: flex; justify-content: space-between; align-items: center; font-size: .69rem; text-transform: uppercase; }
.pdos-project-icon { flex: 1 1 auto; min-height: 24px; overflow: hidden; }
.pdos-project-title { flex: 0 0 auto; font-family: var(--display); font-weight: 700; font-size: clamp(1.15rem, min(2.1vw, 3.8vh), 1.9rem); line-height: .95; text-transform: uppercase; }
.pdos-project-desc { flex: 0 0 auto; margin: 6px 0 10px; font-size: .75rem; line-height: 1.45; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.pdos-project-foot { flex: 0 0 auto; display: flex; justify-content: space-between; gap: 1rem; padding-top: 8px; border-top: 1px solid currentColor; font-size: .69rem; text-transform: uppercase; white-space: nowrap; }
.pdos-project-foot > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.pdos-project--music:hover, .pdos-project--music:focus-visible { background: #1ed760; color: #070707; }
.pdos-project--youshant:hover, .pdos-project--youshant:focus-visible { background: #1a0606; color: #fbeee6; }
.pdos-project--where:hover, .pdos-project--where:focus-visible { background: oklch(0.88 0.07 85); color: #070707; }
.pdos-project--speed:hover, .pdos-project--speed:focus-visible { background: oklch(0.74 0.16 0); color: #070707; }
.pdos-project--terminal:hover, .pdos-project--terminal:focus-visible { background: oklch(0.75 0.16 40); color: #070707; }
.pdos-project--crack:hover, .pdos-project--crack:focus-visible { background: #f4f3ef; color: #070707; }
.pdos-champ-card { grid-column: 1 / -1; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: clamp(16px, 2.2vw, 32px); padding: 10px 22px; outline: 1px dashed var(--v2-soft-line); outline-offset: -1px; }
.pdos-champ-card:hover, .pdos-champ-card:focus-visible { background: #f7c947; color: #070707; outline-color: transparent; }
.pdos-champ-lockup { align-self: stretch; display: flex; align-items: center; gap: 20px; min-height: 0; }
/* The sprite frame (ball + bob room + shadow) sits on the card's centre line, so the bob never
   reaches the card edge. */
.pdos-champ-ball { width: clamp(56px, 6vw, 90px); align-self: stretch; align-items: center; justify-content: center; }
.pdos-champ-word { margin: 0; font-family: var(--display); font-weight: 700; font-size: clamp(1.9rem, min(4.2vw, 6.6vh), 3.9rem); line-height: .88; text-transform: uppercase; white-space: nowrap; }
.pdos-champ-copy { min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.pdos-champ-meta { display: flex; gap: 10px; align-items: center; font-size: .69rem; text-transform: uppercase; }
.pdos-champ-desc { max-width: 62ch; font-size: .82rem; line-height: 1.45; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.pdos-champ-chips { display: flex; flex-wrap: wrap; gap: 6px; font-size: .62rem; letter-spacing: .04em; text-transform: uppercase; }
.pdos-champ-chips span { border: 1px solid currentColor; padding: 3px 7px; }
.pdos-champ-cta { display: flex; flex-direction: column; align-items: flex-end; gap: 10px; font-size: .69rem; text-transform: uppercase; white-space: nowrap; }
.pdos-champ-insert { border: 1px solid currentColor; padding: 12px 16px; font-size: .75rem; font-weight: 600; letter-spacing: .05em; }

/* Windows over the page (projects, Champion Run). Moved to the end of .portfolio-v2 by
   initProjects so no section's clip-path or transform can trap them. */
.pdos-overlay { position: fixed; inset: 0; z-index: 80; display: flex; align-items: center; justify-content: center; padding: 52px 16px 16px; }
.pdos-overlay[hidden] { display: none; }
.pdos-overlay-scrim { position: absolute; inset: 0; background: rgba(0, 0, 0, .6); }
.pdos-dialog { position: relative; max-width: 100%; max-height: 100%; display: flex; flex-direction: column; background: var(--v2-panel); color: var(--v2-fg); box-shadow: 0 0 0 1px var(--v2-line), 14px 14px 0 rgba(0, 0, 0, .55); outline: 0; }
.pdos-dialog .pdos-window-bar { --bar: var(--dialog-bar, var(--v2-fg)); color: #070707; }
.pdos-close { padding: 0 4px; border: 0; background: none; color: inherit; font: inherit; font-size: .85rem; cursor: pointer; }
.pdos-close:hover, .pdos-close:focus-visible { outline: 1px solid currentColor; }
.pdos-dialog--project { width: 780px; }
.pdos-dialog-body { min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 12px; padding: 20px; }
.pdos-dialog-meta { display: flex; justify-content: space-between; font-size: .69rem; text-transform: uppercase; }
.pdos-dialog-title { margin: 0; font-family: var(--display); font-weight: 700; font-size: clamp(2rem, min(5vw, 8vh), 4rem); line-height: .92; text-transform: uppercase; }
.pdos-dialog-desc { margin: 0; font-size: .875rem; line-height: 1.5; }
.pdos-dialog-stage { position: relative; height: clamp(200px, 42vh, 440px); background: repeating-linear-gradient(45deg, rgba(128, 128, 128, .12) 0 6px, transparent 6px 12px); display: flex; align-items: flex-end; padding: 10px; color: var(--v2-dim); font-size: .69rem; text-transform: uppercase; }
.pdos-dialog-foot { display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; padding-top: 10px; border-top: 1px solid var(--v2-soft-line); font-size: .69rem; letter-spacing: .05em; text-transform: uppercase; }
.pdos-dialog-foot > span:first-child { color: var(--v2-dim); }
html.pdos-locked { overflow: hidden; }
/* Keep the scrollbar gutter while locked, so opening a window does not shift the page sideways. */
html { scrollbar-gutter: stable; }

/* Champion Run setup window (Phase 5). */
.pdos-dialog--champ { --dialog-bar: #f7c947; width: min(1320px, 100%); height: 100%; }
/* The Very Best: the game viewport and its boot screen (painted before /vr/vr.css loads). */
.tvb { position: relative; flex: 1 1 auto; min-height: 0; overflow: hidden; background: #0d0d10; color: #f4f3ef; font-family: 'PixC', 'Pixelify Sans', ui-monospace, monospace; }
.tvb-sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.tvb-screen--boot { position: absolute; inset: 0; display: grid; place-items: center; padding: 16px; }
.tvb-boot { width: min(100%, 420px); display: flex; flex-direction: column; align-items: center; gap: 12px; text-align: center; }
.tvb-boot-logo { width: 100px; height: 100px; image-rendering: pixelated; }
.tvb-boot-name { margin: 0; color: #b4b3ad; font-size: .72rem; letter-spacing: .12em; text-transform: uppercase; }
.tvb-boot-title { margin: 0; font-size: clamp(1.6rem, 5vw, 2.4rem); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
.tvb-boot-bar { width: 100%; height: 18px; padding: 3px; border: 3px solid #f4f3ef; }
.tvb-boot-bar span { display: block; width: 0; height: 100%; background: repeating-linear-gradient(90deg, #f7c947 0 10px, transparent 10px 12px); transition: width .2s steps(4); }
.tvb-boot-log { margin: 0; min-height: 1.3em; color: #f7c947; font-size: .78rem; }
.tvb-boot-actions { display: flex; gap: 8px; }

/* Toolbox (Phase 6): 3x3 grid; opening a tool shrinks the grid and slides in a 520px panel. */
.pdos-toolbox { flex: 1 1 auto; min-height: 0; display: flex; overflow: hidden; background: var(--v2-panel); }
.pdos-toolbox-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 14px; padding: clamp(10px, 1.8vh, 16px); }
.pdos-toolbox-title { flex: 0 0 auto; margin: 0; overflow: hidden; font-family: var(--display); font-weight: 700; font-size: clamp(1.8rem, min(4.6vw, 7.6vh), 4.75rem); line-height: 1.02; text-transform: uppercase; white-space: nowrap; }
.pdos-tools { flex: 1 1 auto; min-height: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-rows: repeat(3, minmax(0, 1fr)); gap: 8px; }
.pdos-tool {
  min-width: 0; min-height: 0; overflow: hidden; display: flex; flex-direction: column; padding: clamp(8px, 1.4vh, 14px) 16px;
  border: 0; background: var(--v2-panel-raised); color: var(--v2-fg); font: inherit; text-align: left; cursor: pointer;
  transition: background .15s, color .15s;
}
/* Unbuilt tools read as dimmed through --dim text rather than 50% opacity, which fails AA contrast. */
.pdos-tool.is-soon { color: var(--v2-dim); }
.pdos-tool.is-soon .pdos-tool-desc { opacity: 1; }
.pdos-tool:hover, .pdos-tool:focus-visible { background: var(--hover); color: #070707; opacity: 1; }
.pdos-tool:focus-visible { outline: 2px solid var(--v2-fg); outline-offset: 2px; }
.pdos-tool[aria-pressed="true"] { background: var(--v2-fg); color: var(--v2-bg); opacity: 1; }
.pdos-tool-head { display: flex; justify-content: space-between; font-size: .69rem; text-transform: uppercase; }
.pdos-tool-name { margin-top: auto; font-family: var(--display); font-weight: 700; font-size: clamp(1rem, min(1.9vw, 3.4vh), 1.9rem); line-height: 1.2; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pdos-tool-desc { margin-top: 6px; font-size: .75rem; line-height: 1.4; opacity: .75; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.pdos-toolbox.is-open .pdos-tool-desc { display: none; }
.pdos-tool-panel { flex: 0 0 auto; width: 0; overflow: hidden; transition: width .55s cubic-bezier(.7, 0, .2, 1); }
.pdos-toolbox.is-open .pdos-tool-panel { width: min(520px, 55%); }
.pdos-tool-panel-inner { width: 520px; max-width: 100vw; height: 100%; display: flex; flex-direction: column; border-left: 1px solid var(--v2-soft-line); transform: translateX(80px); opacity: 0; transition: transform .55s cubic-bezier(.7, 0, .2, 1), opacity .3s ease .12s; }
.pdos-toolbox.is-open .pdos-tool-panel-inner { transform: none; opacity: 1; }
.pdos-tool-panel-bar { flex: 0 0 auto; height: 30px; display: flex; align-items: center; justify-content: space-between; padding: 0 10px; background: var(--v2-fg); color: var(--v2-bg); font-size: .75rem; font-weight: 500; letter-spacing: .04em; text-transform: uppercase; }
.pdos-tool-panel-body { flex: 1 1 auto; min-height: 0; overflow: auto; overscroll-behavior: contain; display: flex; flex-direction: column; gap: 16px; padding: 20px; background: var(--p0); }
.pdos-tool-panel-name { margin: 0; font-family: var(--display); font-weight: 700; font-size: clamp(1.8rem, 3.4vw, 3rem); line-height: .95; text-transform: uppercase; outline: 0; }
.pdos-tool-soon { display: flex; flex-direction: column; justify-content: center; gap: 8px; padding: 20px; border: 1px solid var(--v2-soft-line); font-size: .69rem; letter-spacing: .05em; text-transform: uppercase; }
.pdos-tool-soon[hidden] { display: none; }
.pdos-tool-soon p { margin: 0; color: var(--v2-dim); font-size: .82rem; line-height: 1.5; letter-spacing: 0; text-transform: none; }
.pdos-tool-panel-foot { margin-top: auto; color: var(--v2-dim); font-size: .62rem; letter-spacing: .06em; text-transform: uppercase; }
/* A borrowed legacy tool modal, shown inline in the panel: no backdrop, no own header or frame. */
.pdos-tool-slot { --sans: var(--mono); }
.pdos-tool-slot .tool-modal { position: static; display: block; z-index: auto; }
.pdos-tool-slot .tool-modal-backdrop, .pdos-tool-slot .tool-modal-head { display: none; }
.pdos-tool-slot .tool-modal-panel { margin: 0; width: auto; max-height: none; overflow: visible; padding: 0; border: 0; background: none; animation: none; }
.pdos-tool-slot .tool-modal-sub { margin-top: 0; }

/* Playlists window (Phase 7): title and the three playlists on the left, listening history right. */
.pdos-window--playlists .pdos-window-body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr); grid-template-rows: auto minmax(0, 1fr); }
.pdos-window--playlists .v2-stage { display: contents; }
.pdos-window--playlists .v2-playlists { grid-column: 1; grid-template-columns: 1fr; grid-template-rows: repeat(3, minmax(0, 1fr)); gap: 8px; min-height: 0; }
.pdos-window--playlists .v2-tracks { grid-column: 2; grid-row: 1 / span 2; }
.pdos-window--playlists .v2-playlist { padding: 12px; outline: 0; transition: background .15s, color .15s; }
.pdos-window--playlists .v2-playlist:hover, .pdos-window--playlists .v2-playlist:focus-within { background: var(--ok); color: var(--on); }
.pdos-window--playlists .v2-playlist .v2-index-row { display: none; }
.pdos-window--playlists .v2-playlist-body { flex: 1 1 auto; min-height: 0; margin: 0; align-items: stretch; }
.pdos-window--playlists .v2-playlist-cover { width: auto; height: 100%; max-height: 120px; }
.pdos-window--playlists .v2-playlist-copy { padding-bottom: 18px; justify-content: flex-end; }
.pdos-window--playlists .v2-playlist-copy p, .pdos-window--playlists .v2-playlist .v2-card-foot a { color: inherit; }
.pdos-window--playlists .v2-playlist .v2-card-foot { border-top-color: currentColor; }

/* Playlists: compact cover cards over the listening-history table. */
.v2-playlists { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.v2-playlist { min-width: 0; padding: clamp(.6rem, 1.5vh, .9rem) clamp(.7rem, 1vw, .95rem); display: flex; flex-direction: column; overflow: hidden; }
.v2-playlist-body { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: clamp(.6rem, 1vw, .9rem); margin-top: clamp(.5rem, 1.8vh, 1.1rem); }
.v2-playlist-cover { width: clamp(56px, min(6vw, 10vh), 110px); aspect-ratio: 1; object-fit: cover; display: block; background: var(--v2-panel-raised); }
.v2-playlist-copy { min-width: 0; display: flex; flex-direction: column; }
.v2-playlist-copy h3 { margin: 0 0 .2rem; font-family: var(--display); font-weight: 400; font-size: clamp(1.2rem, min(2.3vw, 4.6vh), 2.6rem); line-height: 1; text-transform: uppercase; }
.v2-playlist-copy p { margin: 0 0 clamp(.3rem, .9vh, .55rem); font-size: clamp(.56rem, 1.25vh, .72rem); line-height: 1.5; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.v2-playlist .v2-card-foot { margin-top: 0; }

.v2-tracks { min-height: 0; padding: clamp(.6rem, 1.5vh, .9rem) clamp(.7rem, 1vw, .95rem); display: flex; flex-direction: column; overflow: hidden; }
.v2-tracks-head { flex: 0 0 auto; display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem; margin: clamp(.5rem, 2vh, 1.2rem) 0 clamp(.35rem, 1vh, .6rem); }
.v2-tracks-head h3 { margin: 0; font-family: var(--display); font-weight: 400; font-size: clamp(1.5rem, min(3vw, 5.6vh), 3.4rem); line-height: 1; text-transform: uppercase; white-space: nowrap; }
.v2-top-toggle { display: flex; gap: 4px; }
.v2-top-toggle[hidden] { display: none; }
.v2-top-toggle button { padding: .3rem .65rem; border: 0; background: var(--v2-panel-raised); color: var(--v2-fg); font: inherit; font-size: clamp(.54rem, 1.2vh, .68rem); letter-spacing: .06em; text-transform: uppercase; cursor: pointer; }
.v2-top-toggle button[aria-pressed="true"] { background: var(--v2-fg); color: var(--v2-bg); }
.v2-tracks-table { position: relative; flex: 1 1 auto; min-height: 0; display: grid; grid-template-rows: repeat(5, minmax(38px, 1fr)); }
.v2-track-row { min-height: 0; display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1.25fr) minmax(0, 1.6fr) 3rem; align-items: center; gap: clamp(.8rem, 1.6vw, 1.6rem); border-top: 1px solid var(--v2-soft-line); font-size: clamp(.56rem, 1.3vh, .74rem); letter-spacing: .04em; text-transform: uppercase; }
.v2-track-row > span { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.v2-track-row > span:nth-child(2) { color: var(--v2-dim); }
.v2-track-row > span:last-child { text-align: right; }
/* Column headers stay for screen readers; the mockup has no visible header row. */
.v2-track-header { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.v2-track-bar { height: clamp(3px, .55vh, 5px); background: rgba(244, 243, 239, .14); }
.v2-track-bar i { display: block; width: 0; height: 100%; background: var(--v2-fg); }
.v2-track-row a { color: inherit; text-decoration: none; }
.v2-track-row a:hover, .v2-track-row a:focus-visible { text-decoration: underline; }

/* Gig finder */
.v2-gig-controls { flex: 0 0 auto; display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 1rem; background: var(--v2-panel); padding: clamp(.4rem, 1.2vh, .75rem) clamp(.7rem, 1vw, .95rem); font-size: clamp(.56rem, 1.25vh, .72rem); letter-spacing: .05em; text-transform: uppercase; }
.v2-gig-status { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.v2-gig-buttons { display: flex; background: var(--v2-panel-raised); }
.v2-gig-buttons button { width: clamp(32px, 2.8vw, 42px); height: clamp(26px, 4.4vh, 36px); border: 0; background: transparent; color: var(--v2-fg); font: inherit; font-size: .95rem; cursor: pointer; }
.v2-gig-buttons button:hover, .v2-gig-buttons button:focus-visible { background: var(--v2-fg); color: var(--v2-bg); }
.v2-gig-timer { display: flex; align-items: center; justify-content: flex-end; gap: .9rem; white-space: nowrap; }
.v2-gig-progress { width: clamp(50px, 6vw, 96px); height: 1px; background: var(--v2-soft-line); }
.v2-gig-progress span { display: block; width: 0; height: 100%; background: var(--v2-fg); transition: width 1s linear; }
.v2-gigs { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 10px; min-height: 0; }
.v2-gig { min-width: 0; min-height: 0; padding: clamp(.55rem, 1.4vh, .85rem) clamp(.6rem, .9vw, .85rem); display: flex; flex-direction: column; overflow: hidden; }
.v2-gig-art { position: relative; aspect-ratio: 1.05; min-height: 0; margin-top: clamp(.4rem, 1.4vh, .8rem); background: var(--v2-panel-raised); overflow: hidden; }
.v2-gig-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.v2-gig h3 { flex: 0 0 auto; margin: clamp(.45rem, 1.5vh, .85rem) 0 .25rem; font-family: var(--display); font-weight: 400; font-size: clamp(1rem, min(1.7vw, 3.8vh), 2rem); line-height: 1; text-transform: uppercase; }
.v2-gig p { flex: 0 0 auto; margin: 0; font-size: clamp(.52rem, 1.15vh, .66rem); letter-spacing: .04em; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.v2-gig-date { color: var(--v2-dim); }
.v2-gig-link { flex: 0 0 auto; display: block; margin-top: clamp(.35rem, 1vh, .6rem); padding-top: clamp(.45rem, 1.4vh, .85rem); border-top: 1px solid var(--v2-soft-line); text-align: center; font-size: clamp(.56rem, 1.25vh, .72rem); letter-spacing: .05em; text-transform: uppercase; }
.v2-gig-link:hover, .v2-gig-link:focus-visible { text-decoration: underline; text-underline-offset: .3em; }
/* Media tracker cards reuse the gig card. Posters and game covers are portrait: show the whole
   image (contain) over a blurred, dimmed copy that fills the panel, rather than cropping it square. */
.v2-media-art img { position: relative; object-fit: contain; }
.v2-media-art .v2-media-blur { position: absolute; inset: 0; object-fit: cover; filter: blur(18px) brightness(.45); transform: scale(1.15); }
/* Re-release cards name their cinemas: up to three lines, more on narrow screens. */
.v2-media .v2-gig-venue { white-space: normal; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; line-height: 1.35; }
@media (max-width: 900px) { .v2-media .v2-gig-venue { -webkit-line-clamp: 6; } }
.v2-media-status, .v2-media-status:hover { color: var(--v2-dim); text-decoration: none; }
.v2-gig-empty { grid-column: 1 / -1; min-height: 200px; display: flex; align-items: center; justify-content: center; padding: 2rem; color: var(--v2-dim); font-size: clamp(.6rem, 1.4vh, .78rem); letter-spacing: .05em; text-align: center; text-transform: uppercase; }

/* Footer in the scroll-cue style. Resets the legacy global footer{} rule in index.html. */
.v2-footer { display: flex; align-items: center; gap: 1rem; max-width: none; margin: 1.4rem 0 0; padding: 0; border: 0; color: var(--v2-fg); font-size: clamp(.58rem, 1.35vh, .78rem); letter-spacing: .04em; text-transform: uppercase; white-space: nowrap; }
.v2-footer-rule { flex: 1; height: 1px; background: var(--v2-soft-line); }
.v2-footer-links { display: flex; align-items: center; gap: .7rem; }
.v2-footer-links span { color: var(--v2-dim); }
.v2-footer a:hover, .v2-footer a:focus-visible { text-decoration: underline; text-underline-offset: .3em; }

.v2-ref-row { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-bottom: .3rem; }
.v2-scroll-prev { color: var(--v2-dim); font-size: .7rem; letter-spacing: .08em; text-transform: uppercase; white-space: nowrap; }
.v2-scroll-prev:hover, .v2-scroll-prev:focus-visible { color: var(--v2-fg); }
/* CRT power-on transition (Parwani-DOS): outside paging mode these wrappers are inert
   (display:contents — zero effect on phones/continuous scroll). Inside paging mode they
   become the three animated layers from the design handoff. initShell() in ui-v2.js toggles
   .is-active via IntersectionObserver; the reverse (losing .is-active) plays the same
   transition backwards, so it replays on every visit. */
.pdos-crt-clip, .pdos-crt-slide { display: contents; }
.pdos-crt-line { display: none; }

/* Section paging: on desktop/tablet every section is exactly one viewport under the fixed
   nav, and scrolling moves one whole section at a time (native CSS scroll-snap; see
   initShell in ui-v2.js for the IntersectionObserver-driven CRT transition, keyboard 1-7
   and theme switcher). Phones and very short windows fall back to normal document scrolling. */
@media (min-width: 721px) and (min-height: 620px) {
  :root {
    --v2-gutter: calc(12px * var(--pdos-s, 1)); /* the mockup's 12px edge, scaled like Home */
    --v2-nav-top: 0px;
    --v2-nav-h: 40px;
    --v2-stage-top: calc(var(--v2-nav-top) + var(--v2-nav-h) + clamp(.6rem, 1.6vh, 1.1rem));
  }
  html { scroll-snap-type: y mandatory; }
  .portfolio-v2 { padding: 0 var(--v2-gutter); }
  .v2-nav { position: fixed; top: 0; left: 0; right: 0; min-height: var(--v2-nav-h); padding: 0 var(--v2-gutter); }
  .v2-section {
    height: 100vh;
    height: 100dvh;
    position: relative;
    overflow: hidden;
    scroll-snap-align: start;
    scroll-snap-stop: always;
    scroll-margin-top: 0;
  }
  .v2-section + .v2-section { border-top: 0; }

  .pdos-crt-clip {
    display: block;
    position: absolute;
    inset: 0;
    clip-path: inset(49.7% 0 49.7% 0);
    transition: clip-path .6s steps(10);
  }
  .pdos-crt-slide {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: var(--v2-stage-top) 0 clamp(1rem, 3vh, 2.2rem);
    transform: translateY(40px);
    opacity: 0;
    transition: transform .55s cubic-bezier(.2, .8, .2, 1) .18s, opacity .3s steps(3) .12s;
  }
  .pdos-crt-line {
    display: block;
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 4px;
    margin-top: -2px;
    background: var(--fg);
    box-shadow: 0 0 22px var(--fg);
    transform: scaleX(.12);
    opacity: 1;
    transition: transform .32s steps(4), opacity .2s steps(2) .38s;
    pointer-events: none;
    z-index: 5;
  }
  .v2-section.is-active .pdos-crt-clip { clip-path: inset(0 0 0 0); }
  .v2-section.is-active .pdos-crt-slide { transform: translateY(0); opacity: 1; }
  .v2-section.is-active .pdos-crt-line { transform: scaleX(1); opacity: 0; }

  /* Scanline overlay (global shell, missed in Phase 1 — added here 2026-10-07): a very faint
     CRT screen-door texture over every section, regardless of theme. */
  .v2-section::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: repeating-linear-gradient(0deg, rgba(255, 255, 255, .025) 0 1px, transparent 1px 3px);
  }

  .pdos-crt-slide > .v2-scroll-next { margin-top: auto; padding-top: clamp(.6rem, 2vh, 1.4rem); }
  .pdos-crt-slide > .v2-footer { margin-top: auto; padding-top: clamp(.6rem, 2vh, 1.4rem); }

  /* Fit every section to the stage: the header keeps its size, the stage takes whatever
     height is left, and cards/type scale with viewport height as well as width. */
  .v2-section-head { flex: 0 0 auto; margin-bottom: 0; }
  .v2-section-title { margin: .1rem 0 .35rem; font-size: clamp(3rem, min(10.5vh, 8vw), 7.4rem); line-height: .86; }
  .v2-section-kicker { margin: 0 0 clamp(.5rem, 1.5vh, 1rem); font-size: clamp(.72rem, 1.9vh, 1.1rem); }
  .v2-stage { flex: 1 1 auto; min-height: 0; }
  .v2-index-row { font-size: clamp(.6rem, 1.35vh, .8rem); }

  .v2-strip { font-size: clamp(.62rem, 1.4vh, .78rem); padding: clamp(.45rem, 1.3vh, .8rem) 1rem; }


  .v2-playlists { flex: 0 0 auto; }
  .v2-tracks { flex: 1 1 0; }
  .v2-tracks-table { grid-template-rows: repeat(5, minmax(0, 1fr)); }
  .v2-gigs { flex: 1 1 auto; }
  .v2-gig-art { flex: 1 1 0; aspect-ratio: auto; }
}

/* Short laptop viewports (e.g. 1366x768 screens minus browser chrome): tighten spacing and
   drop purely decorative lines so every card still fits its section. */
@media (min-width: 721px) and (min-height: 620px) and (max-height: 760px) {
  .v2-metric h3 { margin-top: .3rem; }
}
/* Home on desktop/tablet (2026-10-07): drawn on the mockup's own canvas — 1440 design px wide,
   scaled by --pdos-s = min(width / 1440, height / 900), floored at .75 (initHomeScale in
   ui-v2.js) — so its proportions match the Claude Design reference 1:1 at any window size. The
   canvas spans the full window width under the 40px nav, like the mockup. Every size inside is
   the mockup's px value; nothing here may use vw/vh, which would not scale with the canvas. */
.pdos-stage { display: contents; }
@media (min-width: 721px) and (min-height: 620px) {
  :root { --pdos-s: 1; }
  #v2-home { width: auto; margin-inline: calc(-1 * var(--v2-gutter)); }
  .pdos-stage {
    position: absolute;
    top: var(--v2-nav-h);
    left: 0;
    width: calc(100% / var(--pdos-s));
    height: calc((100% - var(--v2-nav-h)) / var(--pdos-s));
    transform: scale(var(--pdos-s));
    transform-origin: 0 0;
    display: flex;
    flex-direction: column;
    container-type: size;
  }
  #v2-home .pdos-home { padding: 12px; gap: 10px; grid-template-columns: minmax(0, 1fr) 330px; }
  #v2-home .pdos-home-left { gap: 10px; }
  #v2-home .pdos-home-right { gap: 8px; }
  /* The title's widest line ("PORTFOLIO." is 5.07em) fills the space the mockup gives it at 1440
     wide (canvas minus right column, about.txt and gaps = 754px), capped by the canvas height so
     the tiles keep the mockup's share of it; on wider windows about.txt takes the extra width. */
  #v2-home .pdos-title-row { grid-template-columns: auto minmax(380px, 1fr); }
  #v2-home .pdos-title-cell { container-type: normal; }
  #v2-home .pdos-title-cell .v2-display { font-size: min((100cqw - 754px) * .195, 15cqh); line-height: 1; }
  #v2-home .pdos-widget-head { height: 26px; padding: 0 8px; font-size: 11px; }
  #v2-home .pdos-widget-body { padding: 12px; }
  #v2-home .pdos-widget-foot { padding: 0 12px 10px; font-size: 10px; }
  #v2-home .pdos-widget-label { font-size: 11px; }
  #v2-home .pdos-about-body { justify-content: space-between; gap: 10px; }
  #v2-home .pdos-about-body p { margin: 0; max-width: 30em; font-size: 15px; line-height: 1.5; text-wrap: pretty; }
  #v2-home .pdos-boot-log { margin-top: auto; padding-top: 8px; gap: 0; font-size: 10px; line-height: 1.7; }
  #v2-home .v2-about-date { margin-top: 0; font-size: 10px; }
  #v2-home .pdos-tiles { gap: 8px; }
  #v2-home .pdos-tile { padding: 14px; }
  #v2-home .pdos-tile-head { font-size: 11px; }
  #v2-home .pdos-tile-title { margin-top: 8px; font-size: 34px; }
  #v2-home .pdos-tile-foot { padding-top: 8px; gap: 3px; font-size: 13px; line-height: 1.35; }
  #v2-home .pdos-tile-foot > span:first-child { font-size: 10px; }
  #v2-home .pdos-extras { gap: 8px; font-size: 12px; }
  #v2-home .pdos-extra { padding: 8px 14px; gap: 12px; }
  #v2-home .pdos-weather .v2-value { font-size: 36px; line-height: 1; }
  #v2-home #v2WeatherExtras { display: none; }
  #v2-home .v2-sun { width: 36px; height: 36px; }
  #v2-home .v2-metric-foot, #v2-home .v2-spotify-state { font-size: 10px; }
  #v2-home .v2-spotify-art { width: 44px; }
  #v2-home .pdos-spotify-body { gap: 12px; }
  #v2-home .pdos-mini-grid { gap: 8px; }
  #v2-home .pdos-mini-grid .v2-value { font-size: min(32px, 34cqw); }
  #v2-home .v2-steps-value { margin: 0 0 8px; font-size: min(32px, 19cqw); }
  /* The mockup's right column is compact so headlines.feed keeps ~200px: steps.sys already names
     the count, and a footer line sits close under its body. */
  #v2-home .v2-steps-label { display: none; }
  #v2-home .v2-steps-value { margin-top: auto; }
  #v2-home .pdos-widget-body:has(+ .pdos-widget-foot) { padding-bottom: 4px; }
  #v2-home .v2-game-art--portrait { width: 30px; }
  #v2-home .v2-value small, #v2-home .v2-steps-value small { font-size: 13px; }
  #v2-home .v2-steps-goal { margin-top: 6px; font-size: 10px; }
  #v2-home .pdos-headlines-body { padding: 14px; gap: 10px; }
  #v2-home .pdos-game-body { gap: 10px; }
  #v2-home .v2-game-text h3 { font-size: 18px; }
  #v2-home .v2-game-text p { font-size: 10px; }
  #v2-home .pdos-dissertation-body { gap: 10px; }
  #v2-home .pdos-dissertation-body h3 { font-size: 20px; }
  #v2-home .pdos-dissertation-body a { font-size: 11px; }
  #v2-home .pdos-status-bar { height: 30px; margin-top: 0; padding: 0 16px; border-top: 1px solid var(--v2-soft-line); font-size: 11px; letter-spacing: .05em; }
}
/* Very short screens: the Champion Run card drops its modifier chips (the window lists them). */
@media (min-width: 721px) and (min-height: 620px) and (max-height: 700px) {
  .pdos-champ-chips { display: none; }
  .pdos-window--playlists .v2-playlist-copy { padding-bottom: 8px; }
  .pdos-window--playlists .v2-playlist { padding: 8px 12px; }
}

@media (max-width: 720px) {
  .portfolio-v2 { padding-inline: .7rem; }
  /* The typed command line is decorative (aria-hidden) and the first thing to go when the
     bar can't fit brand + theme switcher + section counter + clock on one line. */
  .v2-nav { position: relative; display: flex; flex-wrap: nowrap; justify-content: space-between; gap: .5rem; padding: .5rem .6rem; font-size: .66rem; }
  .pdos-cmd { display: none; }
  .pdos-theme-btn span:last-child { display: none; }
  .pdos-right { gap: .6rem; }
  .v2-display { font-size: clamp(3.25rem, 17vw, 6rem); white-space: normal; line-height: .92; }
  /* Phones scroll normally: Home becomes a single stacked column — title, about, tiles (2x3),
     extras, then every right-column widget full width, each given enough height to read. */
  .pdos-home { grid-template-columns: 1fr; grid-template-rows: none; gap: 14px; }
  .pdos-home-left { grid-template-rows: none; gap: 14px; }
  .pdos-home-right { grid-template-rows: none; gap: 10px; }
  .pdos-title-row { grid-template-columns: 1fr; gap: 10px; }
  .pdos-title-cell { align-items: flex-start; }
  .pdos-about-body { min-height: 120px; }
  .pdos-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: repeat(3, minmax(150px, auto)); }
  .pdos-tile-title { font-size: 1.5rem; }
  .pdos-extras { grid-template-columns: minmax(0, 1fr); }
  .pdos-weather-body, .pdos-spotify-body, .pdos-game-body { min-height: 72px; }
  .pdos-mini-grid { grid-template-rows: minmax(110px, auto); }
  /* fitHeadline() (ui-v2.js) binary-searches a font size against this box's clientHeight, so it
     needs a real ceiling here, not min-height — otherwise an auto-height box just grows to fit
     whatever size it tries and the search never actually shrinks anything. */
  .pdos-headlines-body { height: 170px; overflow: hidden; }
  .pdos-headlines-body h2 { font-size: clamp(1.4rem, 7vw, 2rem); }
  .pdos-dissertation-body { min-height: 56px; flex-direction: column; align-items: flex-start; gap: .3rem; }
  .v2-value { font-size: 2.6rem; }
  .pdos-weather .v2-value { font-size: 1.8rem; }
  .v2-game-text h3 { font-size: 1rem; }
  .pdos-status-bar { flex-wrap: wrap; }
  .v2-playlists { grid-template-columns: 1fr; }
  .v2-gigs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .v2-score { --v2-score-size: 92px; }
  .v2-strip { flex-direction: column; }
  .v2-tracks-head { flex-wrap: wrap; }
  /* Phase 4-7 windows on phones: everything stacks and grows with its content. */
  .pdos-window-bar > span:last-child:not(:only-child) { display: none; }
  .pdos-window-bar > .pdos-close { display: block !important; }
  .pdos-projects { grid-template-columns: 1fr; grid-template-rows: none; grid-auto-rows: minmax(210px, auto); padding: 8px; }
  .pdos-project-title { font-size: 1.5rem; }
  .pdos-project-icon { flex: 0 0 96px; margin: 8px 0; }
  .pdos-project-desc, .pdos-champ-desc, .pdos-tool-desc { font-size: .75rem; }
  .pdos-project-head, .pdos-project-foot, .pdos-champ-meta, .pdos-champ-cta, .pdos-champ-chips, .pdos-tool-head, .pdos-dialog-meta, .pdos-dialog-foot,
  .pdos-sec-kicker, .pdos-tool-panel-foot { font-size: .75rem !important; }
  .pdos-champ-card { grid-template-columns: 1fr; grid-auto-rows: auto; gap: 14px; padding: 16px; }
  .pdos-champ-lockup { height: 120px; }
  .pdos-champ-cta { align-items: flex-start; }
  .pdos-overlay { padding: 8px; }
  .pdos-dialog--project, .pdos-dialog--champ { width: 100%; height: 100%; }
  .pdos-toolbox-title { font-size: clamp(1.5rem, 8vw, 2.2rem); white-space: normal; }
  .pdos-tools { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: none; grid-auto-rows: minmax(120px, auto); }
  .pdos-tool-panel { position: fixed; inset: 0; z-index: 90; width: 100% !important; transform: translateX(100%); transition: transform .4s cubic-bezier(.7, 0, .2, 1); }
  .pdos-toolbox.is-open .pdos-tool-panel { transform: none; }
  .pdos-tool-panel-inner { width: 100%; }
  .pdos-sec-title { font-size: clamp(3rem, 16vw, 4.5rem); }
  .pdos-window--playlists .pdos-window-body { display: flex; }
  .pdos-window--playlists .v2-playlists { grid-template-rows: none; }
  .pdos-window--playlists .v2-playlist-cover { width: 96px; height: 96px; }
  /* Journal on phones: the list stacks above the selected entry and nothing scrolls inside the
     window; picking a row scrolls the entry into view instead (initJournal). */
  .pdos-journal { grid-template-columns: 1fr; }
  .pdos-journal-side { border-right: 0; border-bottom: 1px solid var(--v2-soft-line); }
  .pdos-journal-title { font-size: clamp(3rem, 18vw, 5rem); }
  .pdos-journal-list, .pdos-journal-article { overflow: visible; }
  .pdos-journal-entry { scroll-margin-top: 1rem; }
  .pdos-journal-photo { height: 220px; }
  .pdos-journal-entry-head { padding: 14px 16px 12px; }
  .pdos-journal-article { padding: 16px 16px 24px; }
  .pdos-journal-score { --v2-score-size: 92px; }
  .v2-strip span + span::before { display: none; }
  .v2-track-row { grid-template-columns: minmax(0, 1fr) 4.5rem 2rem; gap: .7rem; }
  .v2-track-row > span:nth-child(2) { display: none; }
  .v2-gig-controls { grid-template-columns: 1fr auto; }
  .v2-gig-credit { left: .45rem; white-space: normal; text-align: right; line-height: 1.25; }
  .v2-media .v2-gig-venue { -webkit-line-clamp: 6; }
  .v2-gig-timer { display: none; }
  .v2-footer { flex-wrap: wrap; justify-content: space-between; white-space: normal; }
  .v2-footer-rule { display: none; }
  /* Phones: no small print below 12px. */
  .v2-index-row, .v2-ref, .v2-scroll-prev, .v2-scroll-next, .v2-card-foot, .v2-metric-foot, .v2-spotify-state, .v2-spotify-status,
  .v2-steps-label, .v2-steps-goal, .v2-about-date, .v2-bottom-card p, .v2-news-desc, .pdos-journal-row-text, .pdos-journal-meta, .pdos-journal-note,
  .v2-journal-media figcaption, .pdos-journal-count, .pdos-journal-foot, .pdos-journal-kicker, .pdos-journal-chip, .pdos-window-bar, .v2-journal-credit, .v2-gig-credit, .v2-playlist-copy p, .v2-track-row, .v2-top-toggle button,
  .v2-gig p, .v2-gig-link, .v2-gig-controls, .v2-strip, .v2-footer,
  .pdos-widget-head, .pdos-widget-tag, .pdos-widget-foot, .pdos-tile-head, .pdos-tile-key, .pdos-tile-foot, .pdos-tile-foot > span:first-child,
  .pdos-extra, .pdos-status-bar, .pdos-boot-log, .v2-game-text p { font-size: .75rem; }
}

/* Pixel icon animations (pdos-icons.js), copied from the design mockup. */
@keyframes pxscroll { from { transform: translateY(0); } to { transform: translateY(-50%); } }
@keyframes pxblink { 50% { opacity: 0; } }
@keyframes pxspin { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@keyframes pxvu { 0% { clip-path: inset(62.5% 0 0 0); } 20% { clip-path: inset(25% 0 0 0); } 40% { clip-path: inset(50% 0 0 0); } 60% { clip-path: inset(0 0 0 0); } 80% { clip-path: inset(37.5% 0 0 0); } }
@keyframes pxrot { to { transform: rotate(360deg); } }
@keyframes pxflame { 0% { opacity: .95; transform: translateY(0); } 50% { opacity: .35; transform: translateY(-100%); } 100% { opacity: .95; transform: translateY(0); } }
@keyframes pxglow { 0%, 100% { filter: drop-shadow(0 0 3px #1ed760) drop-shadow(0 0 0 #1ed760); } 50% { filter: drop-shadow(0 0 10px #1ed760) drop-shadow(0 0 22px rgba(30, 215, 96, .6)); } }
@keyframes pxflick { 0%, 100% { opacity: 1; } 37% { opacity: .82; } 41% { opacity: 1; } 73% { opacity: .9; } }
@keyframes pxfr { 0%, 33% { visibility: visible; } 33.1%, 100% { visibility: hidden; } }
@keyframes pxfirepulse { from { opacity: .6; transform: scale(.96); } to { opacity: 1; transform: scale(1.06); } }
@keyframes pxshake { 0% { transform: translate(0, 0); } 50% { transform: translate(2px, -1px); } 100% { transform: translate(-1px, 1px); } }
@keyframes crbob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-16%); } }
@keyframes crshadow { 0%, 100% { transform: scaleX(1); opacity: .55; } 50% { transform: scaleX(.62); opacity: .25; } }

@media (prefers-reduced-motion: reduce) {
  .pdos-icon * { animation: none !important; transition: none !important; }
  .pdos-tool-panel, .pdos-tool-panel-inner { transition: none !important; }
  .v2-cursor { animation: none; }
  .pdos-crt-clip { clip-path: none !important; transition: none !important; }
  .pdos-crt-slide { transform: none !important; opacity: 0; transition: opacity .2s linear !important; }
  .v2-section.is-active .pdos-crt-slide { opacity: 1; }
  .pdos-crt-line { display: none !important; }
}

/* Crack: its own overlay, drawn in the original site's theme (the pre-DOS look:
   Anton titles, IBM Plex Mono readouts, Inter copy, amber locks). Tokens are --ck-* because the
   overlay sits inside .portfolio-v2, which redefines --display/--mono/--bg for the DOS theme.
   Fonts load when the window first opens (openCrack in ui-v2.js). */
.pdos-dialog--crack {
  --ck-bg: #0A0A0A; --ck-panel: #141414; --ck-fg: #F2F2F0; --ck-dim: #8A8A85; --ck-dimmer: #4A4A46;
  --ck-line: rgba(242, 242, 240, .14); --ck-amber: #EDC001;
  --ck-display: 'Anton', sans-serif; --ck-mono: 'IBM Plex Mono', monospace; --ck-sans: 'Inter', sans-serif;
  width: min(1160px, 100%); background: var(--ck-bg); color: var(--ck-fg); font-family: var(--ck-sans);
  box-shadow: 0 0 0 1px var(--ck-line), 0 30px 80px rgba(0, 0, 0, .6); -webkit-font-smoothing: antialiased;
}
.pdos-dialog--crack *, .pdos-dialog--crack *::before, .pdos-dialog--crack *::after { box-sizing: border-box; }
.pdos-dialog--crack .ck-topbar { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: .95rem clamp(1rem, 2.6vw, 2rem); border-bottom: 1px solid var(--ck-line); }
.pdos-dialog--crack .ck-file { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--ck-mono); font-size: .7rem; color: var(--ck-dimmer); letter-spacing: .1em; text-transform: uppercase; }
.pdos-dialog--crack .ck-close { flex: 0 0 auto; padding: .35rem 0; border: 0; background: none; cursor: pointer; font-family: var(--ck-mono); font-size: .78rem; letter-spacing: .06em; text-transform: uppercase; color: var(--ck-dim); transition: color .2s; }
.pdos-dialog--crack .ck-close:hover, .pdos-dialog--crack .ck-close:focus-visible { color: var(--ck-fg); outline: 0; text-decoration: underline; text-underline-offset: .3em; }
.pdos-dialog--crack .ck-body { min-height: 0; overflow: auto; display: grid; grid-template-columns: minmax(280px, 380px) minmax(0, 1fr); gap: clamp(1.2rem, 3vw, 2.6rem); padding: clamp(1.2rem, 3vw, 2.4rem) clamp(1rem, 2.6vw, 2rem); }
.pdos-dialog--crack .ck-side { min-width: 0; display: flex; flex-direction: column; }
.pdos-dialog--crack .ck-label { font-family: var(--ck-mono); font-size: .7rem; color: var(--ck-dimmer); letter-spacing: .1em; text-transform: uppercase; }
.pdos-dialog--crack .ck-title { margin: .5rem 0 .9rem; font-family: var(--ck-display); font-weight: 400; text-transform: uppercase; font-size: clamp(2.2rem, min(5vw, 8vh), 3.6rem); line-height: .95; letter-spacing: 0; }
.pdos-dialog--crack .ck-intro { margin: 0 0 1.6rem; color: var(--ck-dim); font-size: .92rem; line-height: 1.6; }
.pdos-dialog--crack .ck-intro b { color: var(--ck-fg); font-weight: 600; }

/* HUD: hairline grid, 2x2 beside the machine */
.pdos-dialog--crack .ck-hud { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px; background: var(--ck-line); border: 1px solid var(--ck-line); }
.pdos-dialog--crack .ck-stat { background: var(--ck-bg); padding: .85rem 1rem; }
.pdos-dialog--crack .ck-stat .v { font-family: var(--ck-mono); font-size: 1.3rem; font-weight: 600; margin-top: .3rem; letter-spacing: .02em; }
/* lives read as redaction bars: solid = held, struck out = spent */
.pdos-dialog--crack .lives { display: flex; gap: .4rem; align-items: center; height: 1.35rem; }
.pdos-dialog--crack .life { width: 28px; height: 13px; border: 1px solid var(--ck-fg); background: var(--ck-fg); position: relative; }
.pdos-dialog--crack .life.last { background: var(--ck-amber); border-color: var(--ck-amber); }
.pdos-dialog--crack .life.spent { background: none; border-color: var(--ck-dimmer); }
.pdos-dialog--crack .life.spent::before, .pdos-dialog--crack .life.spent::after { content: ""; position: absolute; left: 0; right: 0; top: 50%; height: 1px; background: var(--ck-dimmer); }
.pdos-dialog--crack .life.spent::before { transform: rotate(24deg); }
.pdos-dialog--crack .life.spent::after { transform: rotate(-24deg); }

.pdos-dialog--crack .ck-log { flex: 1 1 auto; min-height: 96px; max-height: 220px; margin-top: 1.2rem; overflow-y: auto; border: 1px solid var(--ck-line); background: var(--ck-panel); font-family: var(--ck-mono); font-size: .74rem; color: var(--ck-dim); line-height: 1.9; padding: .8rem 1rem; }
.pdos-dialog--crack .ck-log div span { color: var(--ck-dimmer); }

/* the machine: target, readout, status, lock */
.pdos-dialog--crack .ck-machine { min-width: 0; display: flex; flex-direction: column; justify-content: center; border: 1px solid var(--ck-line); padding: clamp(1.4rem, 3.4vw, 3rem) clamp(1rem, 2.4vw, 2rem); }
.pdos-dialog--crack .ck-target { text-align: center; margin-bottom: 1.6rem; }
.pdos-dialog--crack .ck-target .digits { font-family: var(--ck-mono); font-size: clamp(1rem, 2.2vw, 1.35rem); font-weight: 500; letter-spacing: .72em; padding-left: .72em; color: var(--ck-dim); margin-top: .7rem; }
.pdos-dialog--crack .ck-readout { display: flex; justify-content: center; gap: clamp(.4rem, 1.4vw, 1rem); padding: clamp(1rem, 2.6vw, 2.2rem) 0; }
.pdos-dialog--crack .slot { width: clamp(52px, 8vw, 104px); height: clamp(72px, min(11vw, 17vh), 140px); border: 1px solid var(--ck-line); background: var(--ck-panel); display: flex; align-items: center; justify-content: center; font-family: var(--ck-mono); font-weight: 600; font-size: clamp(2rem, min(5vw, 8vh), 4rem); color: var(--ck-dimmer); position: relative; transition: border-color .18s, color .18s, background .18s; }
.pdos-dialog--crack .slot.active { color: var(--ck-fg); border-color: var(--ck-fg); background: var(--ck-bg); }
.pdos-dialog--crack .slot.active::after { content: ""; position: absolute; left: 12%; right: 12%; bottom: 10px; height: 2px; background: var(--ck-amber); }
.pdos-dialog--crack .slot.locked { color: var(--ck-amber); border-color: var(--ck-amber); background: var(--ck-bg); }
.pdos-dialog--crack .slot.miss { color: var(--ck-fg); border-color: var(--ck-fg); background: #241a1a; }
.pdos-dialog--crack .ck-status { text-align: center; font-family: var(--ck-mono); font-size: .78rem; letter-spacing: .08em; text-transform: uppercase; color: var(--ck-dim); min-height: 1.2em; margin-bottom: 1.6rem; }
.pdos-dialog--crack .ck-status.good { color: var(--ck-amber); }
.pdos-dialog--crack .ck-controls { display: flex; justify-content: center; gap: .8rem; flex-wrap: wrap; }
.pdos-dialog--crack .ck-btn { font-family: var(--ck-mono); font-size: .78rem; text-transform: uppercase; letter-spacing: .08em; padding: .9rem 2.4rem; border: 1px solid var(--ck-line); color: var(--ck-dim); background: none; cursor: pointer; transition: border-color .2s, color .2s, background .2s; }
.pdos-dialog--crack .ck-btn:hover { border-color: var(--ck-fg); color: var(--ck-fg); }
.pdos-dialog--crack .ck-btn.solid { background: var(--ck-fg); color: var(--ck-bg); border-color: var(--ck-fg); }
.pdos-dialog--crack .ck-btn.solid:hover { background: var(--ck-dim); border-color: var(--ck-dim); }
.pdos-dialog--crack .ck-btn:focus-visible { outline: 2px solid var(--ck-amber); outline-offset: 3px; }
.pdos-dialog--crack .ck-hint { text-align: center; font-family: var(--ck-mono); font-size: .7rem; color: var(--ck-dimmer); letter-spacing: .06em; margin-top: 1.2rem; text-transform: uppercase; }

@media (max-width: 900px) {
  .pdos-dialog--crack .ck-body { grid-template-columns: 1fr; }
  .pdos-dialog--crack .ck-machine { order: -1; }
  .pdos-dialog--crack .ck-hud { grid-template-columns: repeat(4, 1fr); }
  .pdos-dialog--crack .ck-log { max-height: 150px; }
}
@media (max-width: 720px) {
  .pdos-dialog--crack { width: 100%; height: 100%; }
  .pdos-dialog--crack .ck-hud { grid-template-columns: repeat(2, 1fr); }
  .pdos-dialog--crack .ck-btn { width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .pdos-dialog--crack .slot, .pdos-dialog--crack .ck-btn, .pdos-dialog--crack .ck-close { transition: none; }
}

/* Journal index stays closed until an article is requested. The reader opens like the Toolbox
   panel: a flex item whose width animates (grid tracks of mixed types snap instead of easing),
   with an inner column fixed at its open width so the article never re-wraps mid-slide. The rows
   ease between their wide and compact sizes on the same curve. */
.pdos-journal { --journal-side: clamp(290px, 31vw, 440px); display: flex; container-type: inline-size; }
.pdos-journal-side { flex: 1 1 auto; transition: border-color .55s; }
.pdos-journal:not(.is-reading) .pdos-journal-side { border-right-color: transparent; }
.pdos-journal-row { align-items: center; transition: grid-template-columns .55s cubic-bezier(.7, 0, .2, 1), gap .55s cubic-bezier(.7, 0, .2, 1), padding .55s cubic-bezier(.7, 0, .2, 1), background .15s; }
.pdos-journal-thumb { transition: width .55s cubic-bezier(.7, 0, .2, 1), height .55s cubic-bezier(.7, 0, .2, 1); }
.pdos-journal-row-title { transition: font-size .55s cubic-bezier(.7, 0, .2, 1); }
.pdos-journal-row-text { transition: gap .55s cubic-bezier(.7, 0, .2, 1); }
.pdos-journal:not(.is-reading) .pdos-journal-row { grid-template-columns: 120px minmax(0, 1fr); gap: 22px; padding: 18px; }
.pdos-journal:not(.is-reading) .pdos-journal-thumb { width: 120px; height: 90px; }
.pdos-journal:not(.is-reading) .pdos-journal-row-title { font-size: clamp(1.5rem, 2.4vw, 2.3rem); }
.pdos-journal:not(.is-reading) .pdos-journal-row-text { gap: 10px; }
/* Article reader shares the page layout: no scrim, modal or scroll lock. */
.pdos-journal-reader { flex: 0 0 auto; width: 0; min-height: 0; overflow: hidden; transition: width .55s cubic-bezier(.7, 0, .2, 1); }
.pdos-journal.is-reading .pdos-journal-reader { width: calc(100% - var(--journal-side)); }
.pdos-journal-reader-inner { width: calc(100cqw - var(--journal-side)); height: 100%; display: flex; flex-direction: column; transform: translateX(80px); opacity: 0; transition: transform .55s cubic-bezier(.7, 0, .2, 1), opacity .3s ease .12s; }
.is-reading .pdos-journal-reader-inner { transform: none; opacity: 1; }
.pdos-journal-reader .pdos-tool-panel-bar { background: #ff8b60; color: #070707; }
.pdos-journal-reader button { background: transparent; border: 0; color: inherit; cursor: pointer; min-width: 32px; min-height: 30px; }
.pdos-journal-row[aria-expanded="true"] { background: var(--v2-panel-raised); box-shadow: inset 3px 0 #ff8b60; }
.pdos-journal-reader .pdos-journal-entry { flex: 1; overflow: hidden; }
@media (max-width: 720px) {
  .pdos-journal:not(.is-reading) .pdos-journal-row { grid-template-columns: 80px minmax(0, 1fr); gap: 12px; }
  .pdos-journal:not(.is-reading) .pdos-journal-thumb { width: 80px; height: 80px; }
  .pdos-journal, .pdos-journal.is-reading { display: flex; flex-direction: column; }
  .pdos-journal-reader { display: none; }
  .is-reading .pdos-journal-reader { display: block; width: auto; border-top: 1px solid var(--v2-soft-line); }
  .pdos-journal-reader-inner { width: auto; }
  .pdos-journal-reader .pdos-journal-entry { min-height: 400px; }
}
@media (prefers-reduced-motion: reduce) {
  .pdos-journal-side, .pdos-journal-row, .pdos-journal-thumb, .pdos-journal-row-title, .pdos-journal-row-text,
  .pdos-journal-reader, .pdos-journal-reader-inner { transition: none; }
}
