/* RootView project page styles.
   One page, one stylesheet, no framework and no build step for the CSS
   itself. The palette is the dark console theme the RootView application
   uses, so the public page and the tool look like the same project.

   The first section is the page shell (palette, typography, header). The
   rest, from "course project header" down, styles the page's own sections. */

:root {
  --bg: #0d1117;
  --bg-raised: #161b22;
  --border: #262d38;
  --text: #d7dee8;
  --text-muted: #8b96a5;
  --accent: #4c9aff;

  /* The amber the application uses for a medium-severity finding. Here it is
     just the accent on the technical-challenge cards. */
  --medium: #d29922;

  --radius: 8px;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.55 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

h1, h2, h3 { line-height: 1.25; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ---------- page shell ---------- */

.topbar {
  display: flex;
  align-items: center;
  gap: 28px;
  padding: 0 24px;
  height: 56px;
  background: var(--bg-raised);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 10;
}

.brand { display: flex; align-items: center; gap: 9px; color: var(--text); }
.brand:hover { text-decoration: none; }
.brand-mark { color: var(--accent); font-size: 19px; }
.brand-name { font-weight: 650; letter-spacing: 0.2px; }

.page { max-width: 1180px; margin: 0 auto; padding: 26px 24px 60px; }

@media (max-width: 640px) {
  .topbar { gap: 16px; padding: 0 14px; }
  .page { padding: 18px 14px 40px; }
}

/* ---------- course project header ---------- */

.project-header {
  padding: 26px 0 30px;
  border-bottom: 1px solid var(--border);
}

.pinfo { margin: 0 0 26px; display: grid; gap: 12px; }

/* Label / value pairs. The label column is fixed so the three rows line up,
   and collapses to stacked rows on narrow screens. */
.pinfo > div {
  display: grid;
  grid-template-columns: 260px 1fr;
  gap: 16px;
  align-items: start;
}

.pinfo dt {
  color: var(--text-muted);
  font-size: 13.5px;
  padding-top: 1px;
}
.pinfo dd { margin: 0; font-size: 14.5px; }

.people { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.people li { font-size: 14px; }

.semester-title {
  margin: 0 0 10px;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 1.2px;
  color: var(--text-muted);
  font-weight: 600;
}

.deliverables { width: 100%; border-collapse: collapse; }

.deliverables th {
  text-align: left;
  font-weight: 500;
  font-size: 14.5px;
  padding: 8px 16px 8px 0;
  white-space: nowrap;
  vertical-align: top;
  width: 260px;
}
.deliverables th .due { color: var(--text-muted); font-weight: 400; }
.deliverables td { padding: 8px 0; font-size: 14.5px; }
.deliverables tr + tr th,
.deliverables tr + tr td { border-top: 1px solid var(--border); }

.doc { white-space: nowrap; }

/* A deliverable with no url yet. Deliberately not a link: a dead hyperlink
   invites a click that goes nowhere. */
.doc-pending {
  color: var(--text-muted);
  opacity: 0.65;
  border-bottom: 1px dotted var(--border);
  cursor: default;
}

/* ---------- hero ---------- */

.hero {
  padding: 54px 0 46px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 8px;
}

.eyebrow {
  margin: 0 0 18px;
  font-size: 12px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--text-muted);
}

.hero h1 {
  margin: 0 0 20px;
  font-size: clamp(28px, 4.4vw, 46px);
  line-height: 1.16;
  letter-spacing: -0.6px;
  font-weight: 680;
  max-width: 22ch;
}

/* The second line is the claim the whole project rests on, so it gets the
   accent rather than the problem statement above it. */
.hero h1 .hl { color: var(--accent); }

.lede {
  margin: 0 0 30px;
  max-width: 62ch;
  font-size: clamp(16px, 1.6vw, 18px);
  line-height: 1.62;
  color: var(--text-muted);
}

/* ---------- section scaffolding ---------- */

.section { padding: 42px 0; border-bottom: 1px solid var(--border); }
.section:last-of-type { border-bottom: none; }

.section-title {
  margin: 0 0 8px;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 1.2px;
  color: var(--text-muted);
  font-weight: 600;
}

/* ---------- algorithms and tools ---------- */

.tool-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

/* One-pixel grid gaps over a border-coloured background draw the dividing
   lines, so the cells read as a single table rather than floating chips. */
.tool {
  background: var(--bg-raised);
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.tool strong { font-size: 14.5px; font-weight: 600; }
.tool span { font-size: 13px; color: var(--text-muted); }

/* ---------- technical challenges ---------- */

.challenge-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 16px;
}

.challenge {
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-left: 3px solid var(--medium);
  border-radius: var(--radius);
  padding: 18px 20px;
}
.challenge h3 { margin: 0 0 9px; font-size: 15.5px; }
.challenge p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--text-muted); }

/* ---------- milestones ---------- */

.milestones {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 16px;
  align-items: start;
}

.milestone {
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px 20px 20px;
}

.milestone header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 10px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--border);
}
.milestone h3 { margin: 0; font-size: 15.5px; }
.milestone .due {
  font-size: 12px;
  color: var(--text-muted);
  font-family: var(--mono);
  white-space: nowrap;
}

.milestone-summary { margin: 0 0 12px; font-size: 13.5px; line-height: 1.55; color: var(--text-muted); }

.tasks { margin: 0; padding: 0; list-style: none; display: grid; gap: 7px; }
.tasks li {
  font-size: 13.5px;
  line-height: 1.45;
  padding-left: 16px;
  position: relative;
}
.tasks li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 7px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  border: 1px solid var(--text-muted);
}

/* ---------- narrow screens ---------- */

@media (max-width: 760px) {
  .hero { padding: 34px 0 32px; }

  /* Stack the label above its value rather than squeezing two columns. */
  .pinfo > div { grid-template-columns: 1fr; gap: 3px; }
  .deliverables th,
  .deliverables td { display: block; width: auto; white-space: normal; }
  .deliverables th { padding-bottom: 2px; }
  .deliverables tr + tr td { border-top: none; }
}

/* ---------- architecture diagrams ---------- */

/* Two diagrams under the summary: the KVM stack a guest runs on, and
   RootView's own layers. Both are hand-written SVG in landing.html, and both
   are interactive without a line of JavaScript -- the published static page
   ships none. Hovering or tab-focusing a shape reveals its description in the
   panel beside it, through the :has() rules further down. */

.arch {
  /* The layer ramp, darkest at the guest and brightening outward, matching the
     idea the diagram is making: the VM is opaque, and every layer RootView
     wraps around it sees a little more. */
  --arch-vm: #1b232e;
  --arch-vmi: #1e4b74;
  --arch-rootview: #2f77c4;
  --arch-api: #62a8ff;
  --arch-engine: #a8ceff;

  /* The stack diagram is not part of that ramp: hardware is the floor, and the
     hypervisor gets the same blue as RootView's core because that is where
     RootView attaches. */
  --arch-hw: #2b3440;
  --arch-core: #2f77c4;

  --arch-sweep: rgba(76, 154, 255, 0.16);

  display: grid;
  grid-template-columns: minmax(0, 1.18fr) minmax(0, 0.82fr);
  grid-template-areas:
    "intro  intro"
    "figure panel";
  gap: 16px;
  margin-top: 20px;
}

/* The second diagram is a separate idea, not a continuation of the first. */
.arch + .arch {
  margin-top: 32px;
  padding-top: 32px;
  border-top: 1px solid var(--border);
}

.arch-intro { grid-area: intro; }
.arch-intro h3 { margin: 0 0 6px; font-size: 15.5px; }
.arch-intro p {
  margin: 0;
  max-width: 72ch;
  font-size: 14px;
  line-height: 1.6;
  color: var(--text-muted);
}

.arch-figure {
  grid-area: figure;
  /* Otherwise the box stretches to the height of the panel beside it and the
     diagram floats in dead space. */
  align-self: start;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px 16px;
}

.arch-hint {
  margin: 0 0 8px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.03em;
  color: var(--text-muted);
}

.arch svg { display: block; width: 100%; height: auto; overflow: visible; }

/* ---------- the shapes ---------- */

.arch-shape rect,
.arch-shape circle {
  stroke: var(--bg-raised);
  stroke-width: 3;
  transition: filter 0.15s ease, stroke 0.15s ease;
}

.arch-shape text {
  font-family: var(--mono);
  font-size: 15px;
  fill: var(--text);
  text-anchor: middle;
  dominant-baseline: middle;
  pointer-events: none;
}
/* Labels sitting on the two brightest rings need dark text to stay readable. */
.arch-shape text.on-light { fill: #0d1117; }
.arch-shape text.on-mid { fill: #f3f7ff; }

.arch-shape:hover rect,
.arch-shape:hover circle { filter: brightness(1.16); }

/* The accent outline is the focus indicator, so the default one is dropped
   rather than drawn on top of it. */
.arch-shape:focus { outline: none; }
.arch-shape:hover rect,
.arch-shape:hover circle,
.arch-shape:focus rect,
.arch-shape:focus circle { stroke: var(--accent); }

.arch-node rect { fill: var(--bg); stroke: var(--border); stroke-width: 1.5; }
.arch-node text { font-size: 13px; }

.arch-link path {
  fill: none;
  stroke: var(--text-muted);
  stroke-width: 1.5;
  stroke-dasharray: 4 4;
  opacity: 0.55;
}
.arch-link polygon { fill: var(--text-muted); opacity: 0.55; }

.arch-sweep {
  pointer-events: none;
  transform-origin: 300px 300px;
  animation: arch-sweep 9s linear infinite;
}
@keyframes arch-sweep {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .arch-sweep { animation: none; }
}

/* ---------- the detail panel ---------- */

.arch-panel {
  grid-area: panel;
  align-self: start;
  min-height: 200px;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  padding: 16px 18px;
}

.arch-panel-eyebrow {
  margin: 0 0 10px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.arch-panel-empty { margin: 0; font-size: 13.5px; color: var(--text-muted); }

.arch-detail { display: none; }
.arch-detail h4 { margin: 0 0 8px; font-size: 15px; color: var(--accent); }
.arch-detail p { margin: 0; font-size: 14px; line-height: 1.62; color: var(--text-muted); }

/* One rule per shape, because a selector cannot pair a shape with its
   description generically. Every data-key below appears once in landing.html;
   adding a shape there means adding its line here. */
.arch:has(.arch-shape:is(:hover, :focus)) .arch-panel-empty { display: none; }

.arch:has([data-key="vms"]:is(:hover, :focus)) .arch-detail[data-key="vms"],
.arch:has([data-key="kvm"]:is(:hover, :focus)) .arch-detail[data-key="kvm"],
.arch:has([data-key="hardware"]:is(:hover, :focus)) .arch-detail[data-key="hardware"],
.arch:has([data-key="vm"]:is(:hover, :focus)) .arch-detail[data-key="vm"],
.arch:has([data-key="vmi"]:is(:hover, :focus)) .arch-detail[data-key="vmi"],
.arch:has([data-key="rootview"]:is(:hover, :focus)) .arch-detail[data-key="rootview"],
.arch:has([data-key="api"]:is(:hover, :focus)) .arch-detail[data-key="api"],
.arch:has([data-key="engine"]:is(:hover, :focus)) .arch-detail[data-key="engine"],
.arch:has([data-key="web"]:is(:hover, :focus)) .arch-detail[data-key="web"] { display: block; }

/* ---------- when there is nothing to hover, or nothing to hover with ----------
   A browser without :has() would show an empty panel forever, and a touch
   screen has no hover at all. Both fall back to the same thing: every
   description listed under the diagram, which is the content, just not the
   interaction. */

.arch-detail + .arch-detail {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

@supports not selector(:has(*)) {
  .arch-hint { display: none; }
  .arch-panel-empty { display: none; }
  .arch-detail { display: block; }
}

/* A touch screen has no pointer to hover with, and on a phone the panel would
   be a long way from the shape anyway. */
@media (hover: none), (max-width: 620px) {
  .arch-hint { display: none; }
  .arch-panel-empty { display: none; }
  .arch-detail { display: block; }
}

/* Below this the two columns are too narrow to read; the panel moves under the
   diagram, where hovering still works on a pointer device. */
@media (max-width: 860px) {
  .arch {
    grid-template-columns: 1fr;
    grid-template-areas:
      "intro"
      "figure"
      "panel";
  }
  .arch-panel { min-height: 0; }
}
