/* ============================================
   Retro Mac OS (System 7) reskin for
   Arjun Manohar's portfolio page
   ============================================ */

:root {
  --desk-top:    #2a2a2a;
  --desk-bottom: #8a8a8a;
  --menubar-bg:  #000000;
  --menubar-fg:  #FFFFFF;
  /* Menu bar height. .desktop subtracts it from the viewport, so the mobile
     override below only has to change this one value. */
  --menubar-h:   22px;
  --window-face: #DDDDDD;
  --panel-bg:    #FFFFFF;
  --bevel-light: #FFFFFF;
  --bevel-mid:   #808080;
  --bevel-dark:  #000000;
  --ink:         #000000;
  --select-bg:   #000000;
  --select-fg:   #FFFFFF;
}

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
}

body {
  background: var(--desk-bottom);
  font-family: 'Apple Garamond', Georgia, 'Times New Roman', serif;
  /* Apple Garamond is a condensed cut of ITC Garamond and paints about 20%
     narrower than a normal-width serif at the same size, so it needs a couple
     of extra pixels to read at the intended size. */
  font-size: 17px;
  color: #000000;
}

/* Silkscreen is a pixel face and has to stay unsmoothed to keep its grid sharp.
   That rule used to sit on body, but the document text is now a serif, which
   needs antialiasing to be legible. So it moved onto the Silkscreen users only. */
.title-bar-text,
.panel h3,
.section-title,
.menubar,
.icon-label,
.cbot-bubble,
#boot {
  font-smooth: never;
  -webkit-font-smoothing: none;
}

a {
  color: var(--ink);
  text-decoration: underline;
}

@font-face {
  font-family: 'Apple Garamond';
  src: url('/arjunmanohar/fonts/apple_garamond/AppleGaramond.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Apple Garamond';
  src: url('/arjunmanohar/fonts/apple_garamond/AppleGaramond-Italic.ttf') format('truetype');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: 'Apple Garamond';
  src: url('/arjunmanohar/fonts/apple_garamond/AppleGaramond-Bold.ttf') format('truetype');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Apple Garamond';
  src: url('/arjunmanohar/fonts/apple_garamond/AppleGaramond-BoldItalic.ttf') format('truetype');
  font-weight: 700;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: 'Silkscreen';
  src: url('/arjunmanohar/fonts/Silkscreen-Regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

.window {
  grid-column: 2;
  grid-row: 1;
  width: 100%;
  max-width: 1400px;
  height: fit-content;
  background: var(--window-face);
  border-top: 2px solid var(--bevel-light);
  border-left: 2px solid var(--bevel-light);
  border-right: 2px solid var(--bevel-dark);
  border-bottom: 2px solid var(--bevel-dark);
}

.title-bar {
  display: grid;
  grid-template-columns: 20px 1fr 20px;
  align-items: center;
  height: 24px;
  padding: 0 4px;
  background-image: repeating-linear-gradient(
    to bottom,
    #000000 0px,
    #000000 1px,
    var(--window-face) 1px,
    var(--window-face) 3px
  );
  border-bottom: 2px solid var(--bevel-dark);
}

.title-bar-button {
  width: 13px;
  height: 13px;
  background: var(--window-face);
  border-top: 1px solid var(--bevel-light);
  border-left: 1px solid var(--bevel-light);
  border-right: 1px solid var(--bevel-dark);
  border-bottom: 1px solid var(--bevel-dark);
}

.title-bar-button.zoom-box {
  justify-self: end;
}

.title-bar-text {
  grid-column: 2;
  justify-self: center;
  background: var(--window-face);
  padding: 0 8px;
  margin: 0;
  font-family: 'Silkscreen', Geneva, sans-serif;
  font-size: 14px;
  font-weight: normal;
  white-space: nowrap;
}

.window-body {
  padding: 16px;
}

.byline {
  margin: 0 0 16px 0;
  font-style: italic;
}

.panel-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  /* Panels size to their own content instead of stretching to the tallest in the
     row. The Profile panel carries the full work history and runs several times
     taller than Highlights or Academic Qualifications, which left those two as
     mostly empty gray boxes. Bottom edges no longer align; that is the tradeoff. */
  align-items: start;
  gap: 8px;
  width: 100%;
  margin: 0 0 16px 0;
}

/* Each grid cell is a stack, not a single panel. CSS grid has no masonry, so a
   flat grid pushed Projects into a second row that began below the very tall
   Profile panel, leaving a column-height hole under Highlights. Stacking
   Highlights and Projects in one cell packs them tight instead. */
.panel-col {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}

.panel {
  background: var(--panel-bg);
  padding: 10px;
  border-top: 1px solid var(--bevel-mid);
  border-left: 1px solid var(--bevel-mid);
  border-right: 1px solid var(--bevel-light);
  border-bottom: 1px solid var(--bevel-light);
}

.panel h3,
.section-title {
  font-family: 'Silkscreen', Geneva, sans-serif;
  font-size: 12px;
  margin: 0 0 8px 0;
}

.panel .panel-glyph,
.section-title .panel-glyph {
  margin-right: 4px;
}

.panel ul {
  margin: 0;
  padding-left: 18px;
}

.panel p {
  margin: 0 0 8px 0;
}

.status-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 20px;
  padding: 0 8px;
  border-top: 2px solid var(--bevel-light);
  font-size: 12px;
}

.resize-corner {
  width: 13px;
  height: 13px;
  background-image: repeating-linear-gradient(
    135deg,
    var(--bevel-mid) 0px,
    var(--bevel-mid) 1px,
    transparent 1px,
    transparent 3px
  );
}

/* ===== Menu bar ===== */

.menubar {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  height: var(--menubar-h);
  padding: 0 8px;
  background: var(--menubar-bg);
  color: var(--menubar-fg);
  font-family: 'Silkscreen', Geneva, sans-serif;
  font-size: 11px;
}

.menu {
  background: none;
  border: none;
  color: var(--menubar-fg);
  font-family: inherit;
  font-size: inherit;
  padding: 0 8px;
  height: 100%;
  cursor: pointer;
}

.menu:hover,
.menu[aria-expanded="true"] {
  background: var(--menubar-fg);
  color: var(--menubar-bg);
}

.menubar-title {
  margin-right: auto;
  padding-left: 4px;
}

.menubar-right {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-left: auto;
  padding-right: 4px;
}

#weather {
  display: flex;
  align-items: center;
  gap: 4px;
}

#weather[hidden] {
  display: none;
}

.icon-group-label {
  display: none;
}

/* ===== Desktop backdrop and icon-field grid rail ===== */

.desktop {
  min-height: calc(100vh - var(--menubar-h));
  background: linear-gradient(to bottom, var(--desk-top), var(--desk-bottom));
  display: grid;
  grid-template-columns: 120px 1fr 120px;
  align-items: start;
  padding: 32px 16px;
  gap: 16px;
}

.icon-field {
  display: contents;
}

/* The two rails are the actual grid items: left rail in column 1, right rail
   in column 3, both in row 1 alongside the window. Each rail stacks its own
   icons, so a tall window can never stretch the spacing between icons and
   icons can never land in the window's column. */
.icon-rail {
  grid-row: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.icon-rail[data-rail="left"] {
  grid-column: 1;
}

.icon-rail[data-rail="right"] {
  grid-column: 3;
}

.icon-field .icon[data-kind="app"] {
  display: none;
}

.icon-rail > .icon {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  width: 100%;
  background: none;
  border: none;
  cursor: pointer;
}

.icon-glyph {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  background: #FFFFFF;
  border-radius: 4px;
}

.icon-glyph svg {
  image-rendering: pixelated;
}

.icon-label {
  font-family: 'Silkscreen', Geneva, sans-serif;
  font-size: 10px;
  color: var(--menubar-fg);
  text-shadow:
    1px 0 0 #000, -1px 0 0 #000,
    0 1px 0 #000, 0 -1px 0 #000;
  text-align: center;
}

.icon.is-selected .icon-label {
  background: var(--select-bg);
  color: var(--select-fg);
  text-shadow: none;
  padding: 0 2px;
}

/* Pinned to the viewport, not placed in the grid. Sitting in grid row 2 put the
   bot below the window, which pushed it under the fold on any viewport shorter
   than ~890px. Fixed positioning keeps it on screen at every scroll position.
   It stays clear of the window horizontally: the window lives in grid column 2
   and never reaches into the 120px column-3 band this occupies, at any width
   down to the 1100px cutoff. Desktop-only by design; the hide rule lives in the
   max-width:1100px block at the end of this file, which must also catch mobile,
   where .icon-field and .icon-rail turn into display:contents and an unhidden
   bot would claim an icon grid cell. */
.claude-bot {
  position: fixed;
  right: 16px;
  bottom: 16px;
}

/* ===== Dancing bot sprite =====
   Pure-CSS pixel sprite. Sized by --cbot-px below: at 6px the stage measures
   114x111, which clears the 120px desktop rail column. Silkscreen resolves to
   the self-hosted @font-face above, so no external font request is made.
   The sequence plays on hover and on keyboard focus, not on a loop. */

/* ============================================================
   claude-bot -- waves, says hi, hops. Plays on hover or focus.
   Every frame moves in whole sprite-pixels, so nothing blurs.
   ============================================================ */

.cbot-stage {
  --cbot-px: 6px;               /* one sprite pixel */
  --cbot-clay: #C4694B;         /* body */
  --cbot-eye: #14171A;          /* eyes */
  --cbot-bone: #EFE9DF;         /* speech bubble */

  display: inline-flex;
  align-items: flex-end;
  justify-content: center;
  padding: calc(var(--cbot-px) * 9) calc(var(--cbot-px) * 3)
           calc(var(--cbot-px) * 1.5);
  cursor: pointer;
}

.cbot-stage:focus-visible { outline: 2px solid var(--cbot-clay); }

.cbot {
  position: relative;
  width: calc(13 * var(--cbot-px));
  height: calc(8 * var(--cbot-px));
  will-change: transform;
}

.cbot i {
  position: absolute;
  left: calc(var(--x) * var(--cbot-px));
  top: calc(var(--y) * var(--cbot-px));
  width: var(--cbot-px);
  height: var(--cbot-px);
  background: var(--cbot-clay);
}

.cbot i.cbot-eye,
.cbot i.cbot-leg,
.cbot i.cbot-arm { height: calc(var(--cbot-px) * 2); }

.cbot i.cbot-eye { background: var(--cbot-eye); }

/* the arm grows upward from a fixed shoulder, so it never detaches */
.cbot i.cbot-arm {
  top: auto;
  bottom: calc(3 * var(--cbot-px));
}

/* the hand, one pixel jutting off the top of the arm */
.cbot-arm::before {
  content: "";
  position: absolute;
  left: calc(var(--cbot-px) * -1);
  top: 0;
  width: var(--cbot-px);
  height: var(--cbot-px);
  background: var(--cbot-clay);
  opacity: 0;
}

/* ---------- speech bubble ---------- */

.cbot-bubble {
  position: absolute;
  left: calc(8.6 * var(--cbot-px));
  bottom: calc(9.8 * var(--cbot-px));
  padding: 0.5em 0.7em 0.55em;
  background: var(--cbot-bone);
  color: #1A1C1F;
  font-family: "Silkscreen", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: calc(var(--cbot-px) * 1.15);
  letter-spacing: 0.04em;
  line-height: 1;
  white-space: nowrap;
  opacity: 0;
  transform-origin: 0 100%;
}

/* stepped pixel tail, pointing down-left into the head */
.cbot-bubble::after {
  content: "";
  position: absolute;
  left: 0;
  top: 100%;
  width: var(--cbot-px);
  height: var(--cbot-px);
  background: var(--cbot-bone);
  box-shadow:
    calc(var(--cbot-px) * -1) var(--cbot-px) 0 var(--cbot-bone),
    calc(var(--cbot-px) * -2) calc(var(--cbot-px) * 2) 0 var(--cbot-bone);
}

/* ---------- the sequence: 1.9s ----------
   0.00-0.15  gather
   0.15-0.85  wave x3
   0.40-1.40  "hi!"
   0.85-1.55  hop x2
   1.55-1.90  settle                                        */

.cbot-stage:hover .cbot,
.cbot-stage:focus-visible .cbot { animation: cbot-hop 1.9s steps(1, end) forwards; }

.cbot-stage:hover .cbot-arm,
.cbot-stage:focus-visible .cbot-arm { animation: cbot-wave 1.9s steps(1, end) forwards; }

.cbot-stage:hover .cbot-arm::before,
.cbot-stage:focus-visible .cbot-arm::before { animation: cbot-hand 1.9s steps(1, end) forwards; }

.cbot-stage:hover .cbot-eye,
.cbot-stage:focus-visible .cbot-eye { animation: cbot-squint 1.9s steps(1, end) forwards; }

.cbot-stage:hover .cbot-leg,
.cbot-stage:focus-visible .cbot-leg { animation: cbot-tuck 1.9s steps(1, end) forwards; }

.cbot-stage:hover .cbot-bubble,
.cbot-stage:focus-visible .cbot-bubble { animation: cbot-say 1.9s steps(1, end) forwards; }

@keyframes cbot-hop {
  0%,  45%  { transform: translateY(0); }
  48%       { transform: translateY(calc(var(--cbot-px) *  1)); }
  52%       { transform: translateY(calc(var(--cbot-px) * -2)); }
  56%       { transform: translateY(calc(var(--cbot-px) * -4)); }
  60%       { transform: translateY(calc(var(--cbot-px) * -4)); }
  64%       { transform: translateY(calc(var(--cbot-px) * -2)); }
  68%       { transform: translateY(0); }
  71%       { transform: translateY(calc(var(--cbot-px) *  1)); }
  75%       { transform: translateY(calc(var(--cbot-px) * -2)); }
  79%       { transform: translateY(calc(var(--cbot-px) * -2)); }
  83%       { transform: translateY(0); }
  86%       { transform: translateY(calc(var(--cbot-px) *  1)); }
  89%, 100% { transform: translateY(0); }
}

/* the arm rises clear of the head; the hand wags between two poses */
@keyframes cbot-wave {
  0%,   8%  { height: calc(var(--cbot-px) * 2); }
  10%       { height: calc(var(--cbot-px) * 4); }
  12%, 44%  { height: calc(var(--cbot-px) * 7); }
  45%       { height: calc(var(--cbot-px) * 4); }
  47%, 100% { height: calc(var(--cbot-px) * 2); }
}

@keyframes cbot-hand {
  0%,   9%  { opacity: 0; transform: translateX(0); }
  10%, 16%  { opacity: 1; transform: translateX(0); }
  17%, 21%  { opacity: 1; transform: translateX(calc(var(--cbot-px) * 2)); }
  22%, 26%  { opacity: 1; transform: translateX(0); }
  27%, 31%  { opacity: 1; transform: translateX(calc(var(--cbot-px) * 2)); }
  32%, 36%  { opacity: 1; transform: translateX(0); }
  37%, 41%  { opacity: 1; transform: translateX(calc(var(--cbot-px) * 2)); }
  42%, 44%  { opacity: 1; transform: translateX(0); }
  45%, 100% { opacity: 0; transform: translateX(0); }
}

/* eyes drop to one pixel at the top of each hop */
@keyframes cbot-squint {
  0%,  55%  { height: calc(var(--cbot-px) * 2); transform: translateY(0); }
  56%, 63%  { height: var(--cbot-px); transform: translateY(var(--cbot-px)); }
  64%, 76%  { height: calc(var(--cbot-px) * 2); transform: translateY(0); }
  77%, 81%  { height: var(--cbot-px); transform: translateY(var(--cbot-px)); }
  82%, 100% { height: calc(var(--cbot-px) * 2); transform: translateY(0); }
}

/* legs tuck up into the body while airborne */
@keyframes cbot-tuck {
  0%,  51%  { transform: translateY(0); }
  52%, 67%  { transform: translateY(calc(var(--cbot-px) * -1)); }
  68%, 74%  { transform: translateY(0); }
  75%, 82%  { transform: translateY(calc(var(--cbot-px) * -1)); }
  83%, 100% { transform: translateY(0); }
}

/* two-frame pop: small, then full size */
@keyframes cbot-say {
  0%,  19%  { opacity: 0; transform: scale(0.55) translateY(calc(var(--cbot-px) * 0.6)); }
  20%, 23%  { opacity: 1; transform: scale(0.55) translateY(calc(var(--cbot-px) * 0.6)); }
  24%, 70%  { opacity: 1; transform: scale(1) translateY(0); }
  71%, 100% { opacity: 0; transform: scale(1) translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .cbot-stage:hover .cbot,     .cbot-stage:focus-visible .cbot,
  .cbot-stage:hover .cbot-arm, .cbot-stage:focus-visible .cbot-arm,
  .cbot-stage:hover .cbot-arm::before, .cbot-stage:focus-visible .cbot-arm::before,
  .cbot-stage:hover .cbot-eye, .cbot-stage:focus-visible .cbot-eye,
  .cbot-stage:hover .cbot-leg, .cbot-stage:focus-visible .cbot-leg {
    animation: none;
  }
  .cbot-stage:hover .cbot-bubble,
  .cbot-stage:focus-visible .cbot-bubble {
    animation: none; opacity: 1; transform: none;
  }
}

/* ===== Menu dropdowns ===== */

.menu-dropdown {
  position: fixed;
  top: 22px;
  z-index: 101;
  min-width: 160px;
  background: var(--window-face);
  border: 1px solid var(--bevel-dark);
  box-shadow: 2px 2px 0 rgba(0,0,0,0.4);
  display: flex;
  flex-direction: column;
  padding: 2px 0;
}

.menu-dropdown[hidden] {
  display: none;
}

.menu-dropdown a,
.menu-dropdown button {
  background: none;
  border: none;
  text-align: left;
  padding: 4px 12px;
  font-family: Geneva, Verdana, Tahoma, sans-serif;
  font-size: 12px;
  color: var(--ink);
  text-decoration: none;
  cursor: pointer;
}

.menu-dropdown a:hover,
.menu-dropdown button:hover {
  background: var(--select-bg);
  color: var(--select-fg);
}

.menu-dropdown hr {
  border: none;
  border-top: 1px solid var(--bevel-mid);
  margin: 2px 0;
}

/* ===== Boot overlay ===== */

#boot {
  position: fixed;
  inset: 0;
  z-index: 999;
  background: #000000;
  color: #FFFFFF;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  font-family: 'Silkscreen', Geneva, sans-serif;
}

#boot[hidden] {
  display: none;
}

.boot-bar {
  width: 200px;
  height: 8px;
  border: 1px solid #FFFFFF;
}

.boot-bar-fill {
  height: 100%;
  width: 0%;
  background: #FFFFFF;
  transition: width 1.4s linear;
}

#boot.is-loading .boot-bar-fill {
  width: 100%;
}

/* ===== Desktop window scrolling ===== */

/* The page itself must never scroll on desktop. Cap the window to the viewport
   and let its body scroll internally, which is what a real System 7 window
   does anyway. 86px = the 22px menu bar plus .desktop's 32px top and bottom
   padding. Scoped to min-width:781px so the mobile sheet, which manages its
   own 100dvh scrolling, is untouched. */
@media (min-width: 781px) {
  .window {
    display: flex;
    flex-direction: column;
    max-height: calc(100vh - 86px);
  }

  .window-body {
    overflow-y: auto;
    min-height: 0;
  }
}

/* ===== Mobile breakpoint (kept last: .desktop override below must win the cascade) ===== */

@media (max-width: 700px) {
  .desktop {
    padding: 0;
  }

  .window {
    max-width: 100%;
    min-height: 100vh;
  }

  .panel-grid {
    grid-template-columns: 1fr;
  }

  /* The stacks exist only to pack the three desktop columns. On one column they
     would nest a flex container inside a grid cell for no reason, and would also
     sit between .panel-grid and the panels that the sheet shows and hides. */
  .panel-col {
    display: contents;
  }

  .panel {
    width: 100%;
  }
}

@media (max-width: 780px) {
  /* A 22px bar cannot hold the title, both menus, the weather and the full
     date at 11px Silkscreen: the title and the clock both wrapped and
     collided. Doubling the height and dropping the title on mobile only
     keeps everything on one line. Desktop keeps the title and 22px. */
  :root {
    --menubar-h: 44px;
  }

  .menubar-title {
    display: none;
  }

  .menubar-right #weather,
  .menubar-right #clock {
    white-space: nowrap;
  }

  html.js .desktop {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    align-content: start;
    justify-items: center;
    gap: 28px 12px;
    padding: 24px 16px 40px;
  }

  html.js .icon-field,
  html.js .icon-rail {
    display: contents;
  }

  html.js .icon-rail > .icon[data-kind="app"] {
    display: flex;
  }

  /* The desktop rails hold icons in the order the two columns need. Mobile
     wants them regrouped by subject, which crosses rail boundaries (Resume
     lives in the right rail but belongs with Profile). Reordering the DOM
     would move icons between rails and change the desktop layout, so the
     mobile grouping is done with `order` instead and the markup is untouched.
     Values run 1..16 in visual order, headings included. */
  html.js .icon-group-label {
    display: flex;
    align-items: center;
    gap: 8px;
    grid-column: 1 / -1;
    justify-self: stretch;
    width: 100%;
    margin: 0;
    font-family: 'Silkscreen', Geneva, sans-serif;
    font-size: 10px;
    color: var(--menubar-fg);
    text-shadow:
      1px 0 0 #000, -1px 0 0 #000,
      0 1px 0 #000, 0 -1px 0 #000;
  }

  /* Trailing rule fills whatever the label leaves of the row. */
  html.js .icon-group-label::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--menubar-fg);
    opacity: 0.5;
  }

  html.js .icon-group-label[data-group="career"]   { order: 1; }
  html.js .icon[data-icon="highlights"]            { order: 2; }
  html.js .icon[data-icon="profile"]               { order: 3; }
  html.js .icon[data-icon="education"]             { order: 4; }
  html.js .icon[data-icon="projects"]              { order: 5; }
  html.js .icon[data-icon="research"]              { order: 6; }
  html.js .icon[data-icon="resume"]                { order: 7; }
  html.js .icon[data-icon="email"]                 { order: 8; }

  html.js .icon-group-label[data-group="socials"]  { order: 9; }
  html.js .icon[data-icon="linkedin"]              { order: 10; }
  html.js .icon[data-icon="instagram"]             { order: 11; }
  html.js .icon[data-icon="github"]                { order: 12; }

  html.js .icon-group-label[data-group="projects"] { order: 13; }
  html.js .icon[data-icon="sam"]                   { order: 14; }
  html.js .icon[data-icon="safe"]                  { order: 15; }
  html.js .icon[data-icon="paper"]                 { order: 16; }

  /* Cap each icon so a long label wraps inside its own column instead of
     painting over its neighbours. */
  html.js .icon-rail > .icon {
    width: auto;
    max-width: 108px;
    gap: 6px;
  }

  html.js .icon-label {
    overflow-wrap: break-word;
    line-height: 1.4;
  }

  html.js .window {
    display: none;
  }
}

@media (max-width: 780px) {
  html.js body.sheet-open .window {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 200;
    max-width: none;
    height: 100dvh;
    overflow-y: auto;
  }

  html.js body.sheet-open .desktop > .icon-field {
    display: none;
  }

  html.js .panel {
    display: none;
  }

  html.js .panel.is-active {
    display: block;
  }

  html.js body.sheet-open {
    overflow: hidden;
  }

  /* The sheet is an aria-modal dialog, so nothing behind it may stay
     reachable. Hiding the menu bar and any open dropdown takes them out of
     the tab order as well as out of view. */
  html.js body.sheet-open .menubar,
  html.js body.sheet-open .menu-dropdown {
    display: none;
  }

  /* On mobile the close box is the sheet's only functional close control
     (see closeBox wiring in arjunmanohar.js), so it needs a visible X.
     Scoped to body.sheet-open so the desktop title bar's close-box stays a
     blank bevel square, matching authentic System 7 chrome. */
  html.js body.sheet-open .close-box {
    position: relative;
  }

  html.js body.sheet-open .close-box::before,
  html.js body.sheet-open .close-box::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 9px;
    height: 1px;
    background: var(--ink);
  }

  html.js body.sheet-open .close-box::before {
    transform: translate(-50%, -50%) rotate(45deg);
  }

  html.js body.sheet-open .close-box::after {
    transform: translate(-50%, -50%) rotate(-45deg);
  }
}

/* ===== Dancing bot visibility (desktop-only, needs right-column room) ===== */

@media (max-width: 1100px) {
  .claude-bot {
    display: none;
  }
}
