/* ---------- hive scene ---------- */

:root {
  /* Tokens scoped to the honeycomb interior only -- everything else in this
     file uses the site-wide tokens declared in index.html's own :root.
     The stage/rim tones below are deliberately derived from the site's own
     --paper/--surface/--line navy tokens (with a touch of warmth mixed in)
     so the interior reads as a room inside this navy site rather than a
     separate warm-brown world. Only the hex fill stays warm/amber -- that's
     the honey glow, meant to read like lit windows in a dark room. */
  --hive-stage: #13203B;
  --hive-stage-2: #0C1425;
  --hive-rim: #26406E;
  --hive-rim-hi: #3F68AD;
  --hive-fill-hi: #FFDD7A;
  --hive-fill-lo: #E9A61B;
  --hive-ink: #131007;
  /* Shared by .hive-hex and its .hive-hex-rim/.hive-hex-fill children so
     the two can never drift apart -- see the .hive-hex rule for why the
     button itself needs this too, not just its decorative children. */
  --hive-hex-clip: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
}

/* Color note: #13203B below is a plain hardcoded fallback background (not
   tied to any JS constant) so the diorama never reads as a black hole if
   hive.png fails to load for any reason. It matches --hive-stage. */

.hive-alt-hint {
  margin: 0 0 0.5rem;
  text-align: center;
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.78rem;
  color: var(--ink-faint);
}

.hive-scene {
  position: relative;
  height: 460px;
  margin-top: 0.5rem;
  background: #13203B;
  border-radius: 8px;
  overflow: hidden;
}

.hive-interior {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse at 50% 38%, rgba(255, 201, 60, 0.16), transparent 60%),
    var(--hive-stage);
}

/* Tiled hex-outline wall behind the comb, so even a couple of projects
   still reads as a honeycomb wall rather than floating in empty space. */
.hive-wall {
  position: absolute;
  inset: 0;
  background-repeat: repeat;
  opacity: 0.24;
  /* Fade the tiled pattern out toward the frame edges so a couple of real
     hexagons read as content sitting in front of ambient wall texture,
     rather than a mostly-empty room -- opaque through the center ~55%,
     fading to transparent at the stage's edges. */
  -webkit-mask-image: radial-gradient(ellipse 62% 62% at 50% 50%, #000 0%, #000 55%, transparent 100%);
  mask-image: radial-gradient(ellipse 62% 62% at 50% 50%, #000 0%, #000 55%, transparent 100%);
}

/* The comb is generated in JS (see buildHiveComb()/positionHiveComb() in
   hive.js): one .hive-hex button per project, positioned/sized in pixels
   from the ported honeycomb layout() algorithm, centered on the stage via
   this flex wrapper. There's no fixed slot ceiling -- the comb always has
   exactly as many hexagons as PROJECTS has entries. */
.hive-comb-stage {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 46px 20px;
}

.hive-comb {
  position: relative;
}

.hive-hex {
  position: absolute;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  /* Without this, the button's real hit-box is the full rectangle, not the
     hexagon it visually looks like -- and since row spacing (1.5x radius)
     is less than a hex's height (2x radius) so rows nest into each other's
     notches, adjacent rows' rectangles genuinely overlap. A click in that
     overlap could land on the wrong project once the comb grows past a
     single row (2 projects fits in one row today, so this was latent, not
     yet visible). Clipping the button itself to the same hexagon shape as
     its .hive-hex-rim/.hive-hex-fill children makes the real hit area match
     what's actually drawn, closing the overlap entirely. */
  clip-path: var(--hive-hex-clip);
}

.hive-hex:focus-visible {
  /* A plain outline draws a rectangle around the element's bounding box,
     not its clip-path hexagon -- drop-shadow renders against the actual
     clipped pixels instead, so the glow hugs the hexagon's real silhouette. */
  filter:
    drop-shadow(0 0 0 2px var(--accent))
    drop-shadow(0 0 6px rgba(255, 201, 60, 0.6));
}

.hive-hex-rim,
.hive-hex-fill {
  position: absolute;
  inset: 0;
  clip-path: var(--hive-hex-clip);
}

.hive-hex-rim {
  background: linear-gradient(155deg, var(--hive-rim-hi), var(--hive-rim) 60%);
  transition: background 0.15s ease;
}

.hive-hex-fill {
  inset: 4.5%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  /* Depth shadow (warm, part of the honey glow) plus a 1px dark hairline
     tinted toward the navy rim/stage -- crisps up the silhouette where the
     rim and fill gradients would otherwise abut with no hard edge. */
  box-shadow:
    inset 0 -6px 10px rgba(74, 45, 0, 0.38),
    inset 0 0 0 1px rgba(7, 10, 16, 0.65);
  background-image:
    radial-gradient(120% 100% at 28% 18%, rgba(255, 255, 255, 0.55), transparent 42%),
    linear-gradient(160deg, var(--hive-fill-hi), var(--hive-fill-lo) 78%);
}

.hive-hex:focus-visible .hive-hex-rim {
  /* Brighten the rim's own navy gradient on focus rather than hue-shifting
     it -- the drop-shadow glow on .hive-hex above is the sole focus color
     signal, so this should read as "lit up," not a different-colored rim. */
  background: linear-gradient(155deg, #6E9BE8, #2B4785 60%);
}

.hive-hex-num {
  font-family: "Archivo", sans-serif;
  font-weight: 800;
  color: var(--hive-ink);
  line-height: 1;
}

.hive-hex-name {
  font-family: "IBM Plex Sans", sans-serif;
  font-weight: 600;
  color: var(--hive-ink);
  text-align: center;
  line-height: 1.15;
  padding: 0 8%;
}

.hive-live-region {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

/* Purely decorative now (mobile only -- see the max-width media query
   below) -- there's no click-to-enter step any more, desktop lands
   straight on the honeycomb interior. */
.hive-landing {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  background: var(--sky);
}

.hive-landing img {
  /* hive.png is square, but .hive-scene is short and wide, so this must
     cap by both axes -- constraining width alone let the image render
     taller than the scene and get clipped by its overflow:hidden, which
     read as the artwork being zoomed in. */
  max-width: 92%;
  max-height: 92%;
  width: auto;
  height: auto;
  display: block;
}

@media (max-width: 640px) {
  /* Below this width the honeycomb interior is hidden entirely and the
     beehive illustration becomes a purely decorative hero image -- the
     static #all-projects list further down the page is the only way to
     browse projects here. Comes after the unconditional rules above so it
     wins the cascade at matching specificity, rather than the other way
     around. */
  .hive-scene { height: 340px; }
  .hive-landing { display: flex; }
  .hive-interior { display: none; }
  .hive-hint { display: none; }
}

/* ---------- static project list (first-class, zero-JS on mobile) ---------- */

.all-projects {
  margin-top: 2rem;
}

@media (min-width: 641px) {
  /* Desktop already has the interactive honeycomb interior as its way to
     browse (see hive.js) -- this static list stays mobile-only now, where
     the honeycomb is disabled and this is the only way to browse. Elements
     stay in the DOM (just visually hidden) so validateHiveData() in hive.js
     can still catch drift between PROJECTS and this list, and so the
     hash-triggered back-link flow is unaffected. */
  .all-projects, .hive-alt-hint { display: none; }
}

.all-projects h2 {
  margin: 0 0 0.9rem;
  font-family: "Fraunces", Georgia, serif;
  font-optical-sizing: auto;
  font-weight: 600;
  font-size: 1.4rem;
  color: var(--ink);
}

.project-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.project-list-link {
  display: flex;
  gap: 1rem;
  align-items: baseline;
  padding: 1rem 1.1rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

.project-list-link:hover,
.project-list-link:focus-visible {
  border-color: var(--accent);
  background: var(--surface-2);
}

.project-list-link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.project-list-num {
  flex: none;
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.85rem;
  color: var(--ink-faint);
}

.project-list-main {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.35rem 0.65rem;
}

.project-list-name {
  font-family: "Archivo", sans-serif;
  font-weight: 800;
  font-size: 1rem;
  color: var(--ink);
}

.project-list-status {
  flex: none;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.project-list-status--shipped {
  color: var(--status-shipped);
  background: var(--status-shipped-bg);
}

.project-list-status--progress {
  color: var(--status-progress);
  background: var(--status-progress-bg);
}

.project-list-status--archived {
  color: var(--status-archived);
  background: var(--status-archived-bg);
}

.project-list-desc {
  flex-basis: 100%;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

/* Bottom-left instruction hint -- near-black scrim with the site's own
   ink color on top, so it sits on the new Hive Signal palette. Always
   visible now (desktop's honeycomb is no longer entered/exited). */
.hive-hint {
  position: absolute;
  bottom: 14px;
  left: 14px;
  z-index: 3;
  margin: 0;
  padding: 6px 10px;
  background: rgba(7, 10, 16, 0.90);
  border-radius: 6px;
  color: var(--ink);
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.72rem;
  pointer-events: none;
}

/* Bottom-right hover readout -- index + title, fades in on hover only.
   Colors/type: Archivo heading, the site's yellow accent for the index
   line. */
.hive-readout {
  position: absolute;
  bottom: 14px;
  right: 14px;
  z-index: 3;
  min-width: 180px;
  padding-left: 12px;
  border-left: 2px solid var(--accent);
  text-align: left;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.16s linear;
}

.hive-readout.visible { opacity: 1; }

.hive-readout-n {
  font-family: "IBM Plex Mono", monospace;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}

.hive-readout-t {
  font-family: "Archivo", sans-serif;
  font-weight: 800;
  font-size: 20px;
  line-height: 1.15;
  color: var(--ink);
}

/* Project modal -- uses this site's own Hive Signal design tokens (black
   ground, blue structure, yellow action); red is retired from decoration
   entirely so it stays a dedicated "bad/danger" signal elsewhere. */
.hive-modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(3, 5, 9, 0.66);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.2s ease;
}

.hive-modal-backdrop.open {
  opacity: 1;
  visibility: visible;
}

.hive-modal {
  width: min(420px, calc(100vw - 2.5rem));
  max-height: calc(100vh - 3rem);
  overflow-y: auto;
  padding: 1.75rem;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
  transform: translateY(8px);
  transition: transform 0.2s ease;
}

.hive-modal-backdrop.open .hive-modal { transform: translateY(0); }

.hive-modal-kicker {
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.5rem;
}

.hive-modal-title {
  margin: 0 0 0.85rem;
  font-family: "Archivo", sans-serif;
  font-weight: 800;
  font-size: 1.6rem;
  line-height: 1.15;
  color: var(--ink);
}

.hive-modal-body {
  margin: 0 0 1rem;
  font-family: "Archivo", sans-serif;
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

.hive-modal-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1.25rem;
}

.hive-modal-tags span {
  padding: 0.2rem 0.6rem;
  border: 1px solid var(--line);
  color: var(--ink-soft);
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.7rem;
}

.hive-modal-actions {
  display: flex;
  gap: 0.75rem;
}

.hive-modal-btn {
  padding: 0.6rem 1.1rem;
  font-family: "Archivo", sans-serif;
  font-weight: 800;
  font-size: 0.85rem;
  text-decoration: none;
  border: none;
  cursor: pointer;
}

.hive-modal-btn-primary {
  background: var(--accent);
  color: var(--on-accent);
}

.hive-modal-btn-ghost {
  background: none;
  color: var(--ink);
  border: 1px solid var(--line);
}

.hive-modal-btn-ghost:hover,
.hive-modal-btn-ghost:focus-visible {
  border-color: var(--accent);
  background: var(--surface-2);
}

.hive-modal-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
