/* =====================================================================
   THE HERO WORDMARK  —  breeder.studio's opening, in block letters.

   The name dominates the first screen. On scroll it leaves with the page,
   the nav lifts to the top edge and stays, and a miniature of the same
   artwork fades in at the centre of that bar.

   Breeder does the stick with `position: fixed` plus a transform on the
   inner nav. We need none of it: `.topbar` is already
   `position: sticky; top: 0`, so this block simply precedes it. Nothing
   here may introduce a transformed ancestor above `.topbar` or sticky
   stops working and the whole handoff goes with it.

   SIZING. One shape everywhere: ["GROW WITH RAM"], 99 columns by 6
   rows, a 16.5:1 rectangle. Width is all that changes.

     width  =  cols x 0.6em x font-size      0.6em is the mono advance

   so font-size = target width / 59.4. Desktop fills the screen up to a
   19px ceiling; the phone takes 70% of it, which is 1.178vw.

   Stacked variants were tried and dropped. ["GROW","WITH RAM"] and
   ["GROW","WITH","RAM"] both exist in wordmark-art.mjs and buy height
   on a phone, but Ram wants one line, and the reason they were reached
   for in the first place — a supposed 5px floor below which the block
   letters stop resolving — turned out not to be real. Rendered and
   looked at, this art is legible down to about 3.2px.
   ===================================================================== */

.wordmark {
  display: block;
  margin: 0 auto;
  width: 100%;
  padding-inline: clamp(6px, 1.2vw, 18px);
  /*  4px in px, not em. The box-drawing glyphs overrun their line box by
      about three pixels and `overflow-y: hidden` was shaving the bottom
      row. Fixed px so it does not scale with the font. */
  padding-block: clamp(14px, 2.2vh, 30px) calc(clamp(10px, 1.6vh, 22px) + 4px);

  font-family: var(--mono);
  font-weight: 700;
  /*  One line: 99 characters, 6 rows, a 16.5:1 rectangle. Sized to fill
      the width, with a ceiling so it stops growing on a wide monitor.
      Height follows from the grid and lands around 16% of the viewport,
      which is the reduction that was asked for.

      1.5vw, NOT the 1.62vw this had. 1.62 is the arithmetically exact
      fit: 99 characters at a 0.6em advance is 59.4em, and 100/59.4 is
      1.68 before padding. Exact means zero tolerance, so on a real
      phone it clipped the last letter off "GROW WITH RAM" — sub-pixel
      rounding, or the fallback mono rendering before JetBrains Mono
      arrives, is enough to tip it over, and overflow-x: hidden then
      eats the M with no warning. 1.5 leaves about 8% of slack and
      changes nothing above 1267px, where the 19px ceiling binds. */
  font-size: min(1.5vw, 19px);
  line-height: 1;
  letter-spacing: 0;
  white-space: pre;
  text-align: center;

  /*  BOTH axes stated. Per spec, setting one to anything but `visible`
      computes the other to `auto`, which gave the machine view a phantom
      vertical scrollbar. */
  overflow-x: hidden;
  overflow-y: hidden;

  color: var(--signal);
  user-select: none;
}

/* =====================================================================
   THE MINIMISE  —  measured off breeder.studio, then rebuilt.

   I first built this as a scroll-scrubbed CSS scroll-timeline. Reading
   their live DOM showed that is not what they do, and theirs is simpler:

     transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)
     transform-origin: 92.5px 0px            (centre-x, top)
     trigger: "invisible absolute top-10 z-10 w-full h-px"

   That last one is a 1px sentinel pinned 40px below the top. An observer
   watches it, and crossing it flips a class. The smoothness is a 300ms
   eased CSS transition between two states, not a value scrubbed against
   scroll position.

   Their resting transform was matrix(6.76324, 0, 0, 6.76324, 0, -353.56)
   on a mark whose own width is 185px, and 185 x 6.763 = 1251px, exactly
   the width of the giant. So the giant and the small mark are the SAME
   element, scaled, and the nav is pushed down 353.56px to clear it.

   Ours keeps two elements, because our art is text rather than an SVG:
   scaling text up 3.4x rasterises soft, whereas our giant can simply
   shrink toward the bar while the small one fades in beneath it. Same
   trigger, same duration, same easing, same origin.

   Better than my scroll-timeline version in three ways: it is what they
   actually do, it needs no @supports fallback, and it works in Firefox
   and under reduced motion (where only the duration drops to zero).
   ===================================================================== */

/*  Breeder's exact trigger geometry: "absolute top-10 ... h-px", i.e. a
    1px line 40px down. Nothing renders; it exists to be observed. */
.hero-sentinel {
  position: absolute;
  top: 40px; left: 0;
  width: 100%; height: 1px;
  pointer-events: none;
  visibility: hidden;
}

.wordmark {
  transform-origin: 50% 0%;
  transition: transform 300ms cubic-bezier(0.4, 0, 0.2, 1),
              opacity   300ms cubic-bezier(0.4, 0, 0.2, 1);
  will-change: transform, opacity;
}

/*  0.295 is our giant's width divided by the mark's: 373 / 1265. The
    giant therefore lands at exactly the size of the mark it hands to,
    so the two read as one object changing size rather than two objects
    swapping. */
body.has-hero.hero-gone .wordmark {
  transform: scale(0.295);
  opacity: 0;
}

/*  THERE IS NO MINIMISE ON A PHONE, because there is no giant to
    minimise. See the `.wordmark { display: none }` rule in the phone
    media query further down for why.

    This is where a phone-specific transform-origin and scale lived,
    tuned twice: 0.37 against a two-line stack, then 0.848 against a
    one-line mark. Both are gone with the giant itself. Everything in
    this section now applies to desktop only.                        */

/*  The mark uses the same 300ms curve, so both halves of the handoff
    move on one clock. */
.mini {
  transition: opacity 300ms cubic-bezier(0.4, 0, 0.2, 1);
}

@media (prefers-reduced-motion: reduce) {
  .wordmark, .mini { transition-duration: 0s; }
}

/* =====================================================================
   THE BAR  —  Contact left, mark centred, the rest right.
   ===================================================================== */

/*  Grid, not absolute centring. Measured: at a 1009px bar the tabs take
    394px, so a 398px mark centred on the BAR spans 305-703 and collides
    with tabs starting at 615. `1fr auto 1fr` makes the browser resolve
    the centre column against the side columns, so it cannot overlap
    however wide the mark gets. */
.topbar-in {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 16px;
  height: var(--bar-h);
}
.tabs-left  { justify-self: start; }
.tabs-right { justify-self: end; }
.tabs-left, .tabs-right { display: flex; gap: 2px; margin-left: 0; }

/* =====================================================================
   THE MENU  —  <details>, so it works with JavaScript switched off.

   The four main links sit inside a <details>. On desktop the summary is
   hidden and the panel is forced open, so the bar looks exactly as it
   did: four tabs in a row. On a phone the summary becomes a MENU button
   and the panel drops below the bar.

   WHY <details> AND NOT A SCRIPT. Every other piece of this site
   renders without JavaScript on purpose, and navigation is the last
   thing that should need a script to work. <details> is a native
   disclosure widget: keyboard operable, announced by screen readers as
   expanded or collapsed, and it needs no JS at all.

   ONE COPY OF THE LINKS. The obvious alternative was a tab row for
   desktop plus a separate menu list for phones, hidden from each other
   by media query. That puts every nav label in the page text twice, on
   a site whose whole argument is being cleanly readable by crawlers.
   ===================================================================== */

.menu { position: static; }

/*  Desktop, which is the default here rather than the override. The
    panel has to be forced visible because the details is closed, and
    that takes two rules, not one: `display` covers engines that hide
    the children outright, and ::details-content covers Chrome 131 and
    later, which hides them with content-visibility on a pseudo-element
    that `display` cannot reach. */
.menu-btn { display: none; }
.menu-panel { display: flex; gap: 2px; }
.menu::details-content { content-visibility: visible; block-size: auto; }

/*  The panel's copy of Contact. The desktop bar has its own in
    .tabs-left, so this one must not render here or Contact appears
    twice in the same row. */
.menu-panel .tab[href$="/contact"] { display: none; }

.mini {
  justify-self: center;
  min-width: 0;
  display: block;
  /*  Visible BY DEFAULT. Inner pages have no giant wordmark, and a
      visitor with no JavaScript never gets the class that reveals it.
      Fail open, the same way the reveal animation does. */
  opacity: 1;
  transition: opacity 260ms var(--ease);
}
.mini pre {
  margin: 0;
  font: 700 clamp(4px, 0.52vw, 7px)/1 var(--mono);
  white-space: pre;
  color: var(--signal);
  user-select: none;
}

/*  On the homepage the mark waits until the giant has left the screen.
    body.has-hero is set by the builder; .hero-gone by an
    IntersectionObserver in v2.js. */
body.has-hero .mini { opacity: 0; pointer-events: none; }
body.has-hero.hero-gone .mini { opacity: 1; pointer-events: auto; }

/*  RAISED from 720px to 800px, 20 Sep 2026, on a measurement.
    At 740px the three bar items had TWO pixels of clearance on each side
    of the centre mark (gap is declared at 16px, so the mark was being
    crushed below it: 224px wide against 280px at 960px). The left
    Contact button, the mark and five nav links do not fit in 740px, and
    the bar only becomes comfortable around 820px, where the same
    measurement reads 31px and 16px.

    So 721-800 now gets the same clean one-row bar as a phone: mark hard
    left, menu button hard right. A tablet is not a narrow desktop, and a
    wordmark jammed between two navigation blocks looked like an
    accident rather than a layout.

    Below 800px the bar stacks. The rules this replaces assumed flexbox:
    `flex-wrap` does nothing to a grid container and `width: 100%` on a
    grid item fills only its own column. So the grid is restated here as
    a single column, with the mark above the scrolling tab strip. */
@media (max-width: 800px) {
  /*  ONE row, breeder.studio's phone bar: the mark hard left, the menu
      button hard right, nothing else.

      This went through two worse versions. First the mark had a row of
      its own above the nav, which cost 39px at the top of the screen.
      Then the mark was dropped from the homepage entirely to reclaim
      that row, which meant scrolling down left you with no mark at all.
      Putting every link inside the menu frees the right-hand side, so
      the mark and the button share one row and neither is sacrificed.  */
  .topbar-in {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "mini right";
    height: auto;
    padding-block: 8px;
    gap: 8px 12px;
    justify-items: stretch;
  }
  /*  LEFT, not centred. Breeder's phone mark sits in the top-left
      corner once the giant has gone, and a 99-character strip centred
      in a bar whose only other item is a button looks like it missed. */
  .mini       { grid-area: mini; justify-self: start; }
  .tabs-right { grid-area: right; justify-self: end; }

  /*  Contact lives in the menu here, with everything else, so its copy
      in the bar goes away and the panel's copy comes back. */
  .tabs-left { display: none; }
  .menu-panel .tab[href$="/contact"] { display: block; }

  /* ---- THE MARK IS VISIBLE FROM THE START -----------------------
     The global rule holds the small mark at opacity 0 on any page with
     a giant wordmark, waiting to fade in once the giant has scrolled
     away. On a phone there is no giant, so it would be waiting for
     something that never happens and the bar would sit empty on the
     left forever. Shown from first paint instead.

     This replaces a block that hid the whole bar until you scrolled
     past the giant, sliding it down on `hero-gone`. It went out with
     the giant: with nothing above the bar there is nothing to reveal
     it, and a header that hides itself on the one screen where it is
     the only navigation is a trap. The bar keeps `position: sticky`
     from v2.css, unchanged.                                          */
  body.has-hero .mini { opacity: 1; pointer-events: auto; }

  /*  The scrolling strip that used to live here is gone. .tabs-right now
      holds one MENU button, so there is nothing to scroll. */

  /* ---- the button ---------------------------------------------- */
  .menu-btn {
    display: inline-flex; align-items: center; gap: 9px;
    font: 500 12px/1 var(--mono);
    letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--dim);
    padding: 11px 13px;
    border: 1px solid var(--rule);
    cursor: pointer;
    user-select: none;
    /*  Both are needed to drop the disclosure triangle: the first is
        the standard, the second is Safari's older pseudo-element. */
    list-style: none;
  }
  .menu-btn::-webkit-details-marker { display: none; }

  /*  A plus that becomes a cross, drawn rather than typed so it lines
      up with the cap height instead of sitting on the baseline. */
  .menu-btn::after {
    content: ""; width: 9px; height: 9px; flex: none;
    background:
      linear-gradient(currentColor, currentColor) center/9px 1px no-repeat,
      linear-gradient(currentColor, currentColor) center/1px 9px no-repeat;
    transition: transform 220ms var(--ease);
  }
  .menu[open] .menu-btn { color: var(--fg); border-color: var(--signal); }
  .menu[open] .menu-btn::after { transform: rotate(45deg); }

  /* ---- the panel ------------------------------------------------ */
  /*  Anchored to .topbar, which is position: sticky and therefore a
      positioned ancestor. Full bleed rather than a floating card: the
      bar is already edge to edge and a narrow dropdown under a
      full-width bar reads as a mistake. */
  .menu { position: static; }
  .menu-panel {
    display: none;
    position: absolute; top: 100%; left: 0; right: 0;
    z-index: 2;
    flex-direction: column; gap: 0;
    padding: 4px 0;
    background: var(--bg-2);
    border-block: 1px solid var(--rule);
  }
  .menu[open] .menu-panel { display: flex; }

  /*  44px tall, which is the smallest touch target worth shipping.
      16px of padding on a 12px line gets there exactly. */
  .menu-panel .tab {
    padding: 16px 20px;
    border: 0;
    border-bottom: 1px solid var(--rule-soft);
  }
  .menu-panel .tab:last-child { border-bottom: 0; }
  .menu-panel .tab[aria-current="page"] {
    color: var(--signal);
    box-shadow: inset 2px 0 0 var(--signal);
  }

  /*  THE GIANT, at 70% of the screen and centred.
      Ram asked for 70% "like breeder". At 99 characters that is 4.1px
      per character and the block letters were measured to stop
      resolving below 5px, so the phone uses the TWO-LINE stack instead
      (see the generated wordmark-art.css). 60 characters at 0.6em means
      70vw needs 70 / (60 x 0.6) = 1.944vw, which lands at 6.8px and an
      82px tall mark: about a tenth of the screen, which is where
      Breeder's own sits. Desktop keeps the single line he asked for.

      There is 30% of the width spare here, so unlike the desktop rule
      this one needs no extra tolerance for a fallback font. */
  /*  NO GIANT WORDMARK ON A PHONE.

      The bar is the header here, from first paint: the small mark sits
      top-left and MENU top-right, and the headline starts immediately
      underneath. Nothing to scroll past before the page says what it
      does.

      This is worth stating because the giant went through four shapes
      on phones before being cut: full-width one line, a two-line stack
      at 70%, a one-line strip at 70%, and a version that hid the whole
      bar until you scrolled past it. The problem underneath all four is
      that "GROW WITH RAM" in block letters is a 16.5:1 rectangle, so on
      a 351px screen it is either wide and only 25px tall, or tall and
      stacked onto lines the brand does not have. Breeder can do this
      because BREEDER is one word.

      The art is `content`, and the <pre> is empty in the HTML, so
      display:none costs nothing and removes no text. The mark's
      accessible name lives on the .mini anchor, which is still here. */
  .wordmark { display: none; }

  /*  THE SMALL MARK, in block art like everything else.

      This was the name set in plain mono for one round, on the grounds
      that a 99-character strip could not be a bar item on a phone: the
      space beside the menu button is 229px at 351px wide, which works
      out at 3.86px per character, and a 5px legibility floor was
      recorded elsewhere in this repo as measured fact.

      It is not fact. Rendering this exact art at 3.2, 3.5, 3.9 and
      4.1px and looking at the result, all four read cleanly as GROW
      WITH RAM. The block alphabet never needed to give up here, and
      the plain-text mark was solving a problem that did not exist.

      1vw rather than the base rule's clamp(4px, 0.52vw, 7px), which
      floors at 4px and renders 238px wide, nine more than fits:

        320px screen   3.2px   190px of art   198px available
        351px screen   3.51px  208px of art   229px available
        412px screen   4.12px  245px of art   290px available

      No .topbar prefix any more. That extra class existed to beat the
      generated wordmark-art.css on specificity; now the generated art
      is exactly what we want, so only the size is overridden. */
  /*  40% smaller on 21 Sep 2026, at Ram's request: the full-width mark
      crowded the bar. It stays hard left. */
  .mini pre { font-size: clamp(1.92px, 0.6vw, 3.6px); }
}

@media print {
  .wordmark, .mini { display: none; }
}

/* =====================================================================
   THE ACCENT PASS  —  more orange, placed rather than sprayed.

   The site had one accent used sparingly. Ram asked for more of it. The
   rule followed here: orange goes on things that are either the BRAND
   or a NUMBER, never on running prose, because body text in orange
   drops to a worse contrast than the near-white it replaces and reads
   as a warning rather than as brand.

   Everything below is var(--signal) at 6.02:1 on the background, which
   clears WCAG AA for both normal and large text.
   ===================================================================== */

/*  The nav's own mark. "Ramakrishnan S" stays white because it is the
    name; the discipline after it takes the accent. */
.brand span { color: var(--signal); }

/*  The hero's answering line. This is the brand statement, so it carries
    the brand colour rather than the dim grey it had. */
.h-sub { color: var(--signal); }

/*  The figures. Numbers are exactly what the accent is for: they are
    scanned, not read, and the colour is doing the pointing. */
.hero-rail dd { color: var(--signal); }

/*  Case meta values, same argument. The labels above them stay dim so
    the number is the thing the eye lands on. */
.case-meta dd { color: var(--signal); }

/*  Interactive edges pick up the accent on hover, so the colour also
    means "this responds". */
.chip:hover { color: var(--signal); border-color: var(--signal); }
.foot-nav a:hover { color: var(--signal); }
.tab:hover { color: var(--signal); border-color: var(--signal); }

/*  The footer signature. */
.foot-name { color: var(--signal); }

/*  THE FREE AUDIT BUTTON (25 Sep 2026). The one filled item in the bar,
    in the accent, so it reads as the action rather than as a sixth tab.
    Desktop: beside Contact in the left column. Phone: first in the menu,
    and its desktop copy goes with .tabs-left. Each copy is display:none
    in the other viewport, like Contact. Added to, never overriding,
    the rules above: the blog loads this file too. */
.tab-cta { margin-left: 8px; color: var(--bg); background: var(--signal); border-color: var(--signal); font-weight: 700; }
.tab-cta:hover, .tab-cta:focus-visible { color: var(--signal); background: transparent; border-color: var(--signal); }
.menu-panel .tab-cta { display: none; }
/*  Measured 25 Sep 2026: beside Contact, the button overlapped the
    centred mark from 801 to about 990px. Contact left the bar on 26 Sep
    (merged into the free audit page), and re-measured alone the button
    clears the mark everywhere, with only 2px to spare at 801px and 16px
    or more from 850px. So it hides only in that tight band. */
@media (min-width: 801px) and (max-width: 849px) {
  .tabs-left .tab-cta { display: none; }
}
@media (max-width: 800px) {
  .menu-panel .tab-cta { display: block; margin-left: 0; }
}
